Hi there,

When we use our custom SQLite function function_sparql_regex (lower in
this E-mail) together with bound values for the argvs of the function,
then sqlite3_reset nor sqlite3_clear_bindings are clearning the auxdata.

This makes it impossible to pass the regex as a sqlite3_bind_text (the
same regex would be used even if you'd pass a new regex string).

The sqlite3_set_auxdata's destroy function ptr is called when you'd
sqlite3_finalize the stmt each time, of course. But then it's not
possible to cache our statements as efficiently as we are doing right
now.

Here's an example that reproduces it:

static sqlite *db = NULL;
static const *filename = "test.db";
static sqlite3_stmt *stmt = NULL;

static void
open_db (void)
{
  sqlite3_open (filename, &db) != SQLITE_OK);
  sqlite3_create_function (db, "SparqlRegex", 3, SQLITE_ANY,
                           priv, &function_sparql_regex, 
                           NULL, NULL);
}

static void
exec_regex (char *regex, char *mod)
{
  if (!stmt) {
        sqlite3_prepare_v2 (db, "SELECT field FROM Table"
                                "WHERE ... AND ... "
                                "SparqlRegex (field, ?, ?)",
                           -1, &stmt, NULL);
  } else {
        sqlite3_reset (stmt);
        sqlite3_clear_bindings (stmt);
  }
  sqlite3_bind_text (stmt, 0, regex, -1, SQLITE_TRANSIENT);
  sqlite3_bind_text (stmt, 1, mod, -1, SQLITE_TRANSIENT);
  ...
  sqlite3_step () ...
  ...
}

static void
app (void)
{
  open_db ();
  exec_regex (".*", "i");
  exec_regex ("foo", "i");
}

-----

static void
function_sparql_regex (sqlite3_context *context,
                       int              argc,
                       sqlite3_value   *argv[])
{
  gboolean ret;
  const gchar *text, *pattern, *flags;
  GRegexCompileFlags regex_flags;
  GRegex *regex;

  if (argc != 3) {
    sqlite3_result_error (context, “Invalid argument count”, -1);
    return;
  }

  regex = sqlite3_get_auxdata (context, 1);
  text = sqlite3_value_text (argv[0]);
  flags = sqlite3_value_text (argv[2]);
  if (regex == NULL) {
    gchar *err_str;
    GError *error = NULL;
    pattern = sqlite3_value_text (argv[1]);
    regex_flags = 0;
    while (*flags) {
      switch (*flags) {
      case ’s’: regex_flags |= G_REGEX_DOTALL; break;
      case ‘m’: regex_flags |= G_REGEX_MULTILINE; break;
      case ‘i’: regex_flags |= G_REGEX_CASELESS; break;
      case ‘x’: regex_flags |= G_REGEX_EXTENDED; break;
      default:
        err_str = g_strdup_printf (”Invalid SPARQL regex flag ‘%c’”, *flags);
        sqlite3_result_error (context, err_str, -1);
        g_free (err_str);
        return;
      }
      flags++;
    }
    regex = g_regex_new (pattern, regex_flags, 0, &error);
    if (error) {
      sqlite3_result_error (context, error->message, error->code);
      g_clear_error (&error);
      return;
    }
    sqlite3_set_auxdata (context, 1, regex, (void (*) (void*)) g_regex_unref);
  }
  ret = g_regex_match (regex, text, 0, NULL);
  sqlite3_result_int (context, ret);
  return;
}

-- 


Philip Van Hoof
freelance software developer
Codeminded BVBA - http://codeminded.be

_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to