[sqlite] Different behaviour of auxiliary data between 3.7.17 and 3.8.0

2014-02-09 Thread gwenn
Hello,
I am not sure but it seems there is a regression between versions
3.7.17 and 3.8.0.
It's impacting custom/user declared function and auxiliary data.

sqlite-amalgamation-3071700 gwen$ gcc
-I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
-I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
sqlite-amalgamation-3071700 gwen$ ./auxdata
loop 1
(0) compiling...
z
(0) reusing...
y
loop 2
(0) reusing...
z
(0) reusing...
y

sqlite-amalgamation-3080300 gwen$ gcc
-I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
-I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
sqlite-amalgamation-3080300 gwen$ ./auxdata
loop 1
(0) compiling...
z
(0) reusing...
y
loop 2
(0) compiling...
z
(0) reusing...
y

The auxiliary data is reused in the second loop with SQLite 3.7.17 but
not with SQLite 3.8.0.
What is the expected/correct behaviour?

Regards

Here is the content of auxdata.c:
#include stdlib.h
#include stdio.h
#include glib.h
#include sqlite3.h

static void log(void *pArg, int iErrCode, const char *zMsg) {
printf((%d) %s\n, iErrCode, zMsg);
}

static void glibRegexpDelete(void *p){
  GRegex *pRegex = (GRegex *)p;
  g_regex_unref(pRegex);
}

static void glibReplaceAllFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
GError *err = NULL;
GRegex *p;
gchar *result = NULL;

(void)argc;  /* Unused parameter */

const gchar *str = (const gchar *) sqlite3_value_text(argv[1]);
if (!str) {
return;
}

const gchar *replacement = (const gchar *) sqlite3_value_text(argv[2]);
if (!replacement) {
sqlite3_result_error(ctx, no replacement string, -1);
return;
}

p = sqlite3_get_auxdata(ctx, 0);
if( !p ){
const gchar *re = (const gchar *) sqlite3_value_text(argv[0]);
if( !re ){
//sqlite3_result_error(ctx, no regexp, -1);
return;
}
p = g_regex_new(re, 0, 0, err);

if( p ){
sqlite3_set_auxdata(ctx, 0, p, glibRegexpDelete);
}else{
char *e2 = sqlite3_mprintf(%s: %s, re, err-message);
sqlite3_result_error(ctx, e2, -1);
sqlite3_free(e2);
g_error_free(err);
return;
}
sqlite3_log(0, compiling...);
} else {
sqlite3_log(0, reusing...);
}

result = g_regex_replace(p, str, -1, 0, replacement, 0, err);
if (err) {
sqlite3_result_error(ctx, err-message, -1);
g_error_free(err);
return;
}
sqlite3_result_text(ctx, result, -1, g_free);
}

int main(int argc, char **argv) {
sqlite3_config(SQLITE_CONFIG_LOG, log, NULL);
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
char *zErrMsg = NULL;
const char *z;
int rc = 0;
rc = sqlite3_open_v2(:memory:, db, SQLITE_OPEN_FULLMUTEX |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (db == NULL || SQLITE_OK != rc) {
fprintf(stderr, Error: unable to open database: %s\n, sqlite3_errmsg(db));
exit(1);
}
sqlite3_create_function_v2(db, regex_replace, 3, SQLITE_UTF8, 0,
glibReplaceAllFunc, NULL, NULL, NULL);
  rc = sqlite3_prepare_v2(db, select regex_replace('.', 'abcde', r)
from (select 'z' as r union all select 'y'), -1, stmt, NULL);
  if (stmt == NULL || SQLITE_OK != rc) {
fprintf(stderr, Error: prepare stmt: %s\n, sqlite3_errmsg(db));
exit(1);
  }
  for (int i = 1; i = 2; i++) {
  printf(loop %d\n, i);
 rc = sqlite3_step(stmt);
 while (rc == SQLITE_ROW) {
  z = (const char*)sqlite3_column_text(stmt, 0);
  printf(%s\n, z);
  rc = sqlite3_step(stmt);
 }
 if (SQLITE_OK != rc  SQLITE_DONE != rc) {
fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
exit(1);
}
 rc = sqlite3_reset(stmt);
 if (SQLITE_OK != rc) {
fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
exit(1);
}
}
  sqlite3_finalize(stmt);
sqlite3_close(db);
}
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Different behaviour of auxiliary data between 3.7.17 and 3.8.0

2014-02-09 Thread Richard Hipp
Can you provide an example program that omits the glib.h dependency?


On Sun, Feb 9, 2014 at 10:50 AM, gwenn gwenn.k...@gmail.com wrote:

 Hello,
 I am not sure but it seems there is a regression between versions
 3.7.17 and 3.8.0.
 It's impacting custom/user declared function and auxiliary data.

 sqlite-amalgamation-3071700 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3071700 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) reusing...
 z
 (0) reusing...
 y

 sqlite-amalgamation-3080300 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3080300 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) compiling...
 z
 (0) reusing...
 y

 The auxiliary data is reused in the second loop with SQLite 3.7.17 but
 not with SQLite 3.8.0.
 What is the expected/correct behaviour?

 Regards

 Here is the content of auxdata.c:
 #include stdlib.h
 #include stdio.h
 #include glib.h
 #include sqlite3.h

 static void log(void *pArg, int iErrCode, const char *zMsg) {
 printf((%d) %s\n, iErrCode, zMsg);
 }

 static void glibRegexpDelete(void *p){
   GRegex *pRegex = (GRegex *)p;
   g_regex_unref(pRegex);
 }

 static void glibReplaceAllFunc(
   sqlite3_context *ctx,
   int argc,
   sqlite3_value **argv
 ){
 GError *err = NULL;
 GRegex *p;
 gchar *result = NULL;

 (void)argc;  /* Unused parameter */

 const gchar *str = (const gchar *) sqlite3_value_text(argv[1]);
 if (!str) {
 return;
 }

 const gchar *replacement = (const gchar *) sqlite3_value_text(argv[2]);
 if (!replacement) {
 sqlite3_result_error(ctx, no replacement string, -1);
 return;
 }

 p = sqlite3_get_auxdata(ctx, 0);
 if( !p ){
 const gchar *re = (const gchar *) sqlite3_value_text(argv[0]);
 if( !re ){
 //sqlite3_result_error(ctx, no regexp, -1);
 return;
 }
 p = g_regex_new(re, 0, 0, err);

 if( p ){
 sqlite3_set_auxdata(ctx, 0, p, glibRegexpDelete);
 }else{
 char *e2 = sqlite3_mprintf(%s: %s, re, err-message);
 sqlite3_result_error(ctx, e2, -1);
 sqlite3_free(e2);
 g_error_free(err);
 return;
 }
 sqlite3_log(0, compiling...);
 } else {
 sqlite3_log(0, reusing...);
 }

 result = g_regex_replace(p, str, -1, 0, replacement, 0, err);
 if (err) {
 sqlite3_result_error(ctx, err-message, -1);
 g_error_free(err);
 return;
 }
 sqlite3_result_text(ctx, result, -1, g_free);
 }

 int main(int argc, char **argv) {
 sqlite3_config(SQLITE_CONFIG_LOG, log, NULL);
 sqlite3 *db = NULL;
 sqlite3_stmt *stmt = NULL;
 char *zErrMsg = NULL;
 const char *z;
 int rc = 0;
 rc = sqlite3_open_v2(:memory:, db, SQLITE_OPEN_FULLMUTEX |
 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
 if (db == NULL || SQLITE_OK != rc) {
 fprintf(stderr, Error: unable to open database: %s\n,
 sqlite3_errmsg(db));
 exit(1);
 }
 sqlite3_create_function_v2(db, regex_replace, 3, SQLITE_UTF8, 0,
 glibReplaceAllFunc, NULL, NULL, NULL);
   rc = sqlite3_prepare_v2(db, select regex_replace('.', 'abcde', r)
 from (select 'z' as r union all select 'y'), -1, stmt, NULL);
   if (stmt == NULL || SQLITE_OK != rc) {
 fprintf(stderr, Error: prepare stmt: %s\n, sqlite3_errmsg(db));
 exit(1);
   }
   for (int i = 1; i = 2; i++) {
   printf(loop %d\n, i);
  rc = sqlite3_step(stmt);
  while (rc == SQLITE_ROW) {
   z = (const char*)sqlite3_column_text(stmt, 0);
   printf(%s\n, z);
   rc = sqlite3_step(stmt);
  }
  if (SQLITE_OK != rc  SQLITE_DONE != rc) {
 fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
 exit(1);
 }
  rc = sqlite3_reset(stmt);
  if (SQLITE_OK != rc) {
 fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
 exit(1);
 }
 }
   sqlite3_finalize(stmt);
 sqlite3_close(db);
 }
 ___
 sqlite-users mailing list
 sqlite-users@sqlite.org
 http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users




-- 
D. Richard Hipp
d...@sqlite.org
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] Different behaviour of auxiliary data between 3.7.17 and 3.8.0

2014-02-09 Thread gwenn
Here you are:

#include stdlib.h
#include stdio.h
#include sqlite3.h

static void reuseAuxDataCountFunc(
  sqlite3_context *ctx,
  int argc,
  sqlite3_value **argv
){
int *reuseAuxDataCount;
int value;
(void)argc;  /* Unused parameter */

reuseAuxDataCount = (int*)sqlite3_get_auxdata(ctx, 0);
if (reuseAuxDataCount == NULL) {
reuseAuxDataCount = (int *)malloc(sizeof(int));
if (reuseAuxDataCount == NULL) {
sqlite3_result_error_nomem(ctx);
return;
}
*reuseAuxDataCount = 0;
sqlite3_set_auxdata(ctx, 0, reuseAuxDataCount, free);
} else {
(*reuseAuxDataCount)++;
}
sqlite3_result_int(ctx, *reuseAuxDataCount);
}

int main(int argc, char **argv) {
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
char *zErrMsg = NULL;
const char *z;
int rc = 0;
rc = sqlite3_open_v2(:memory:, db, SQLITE_OPEN_FULLMUTEX |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (db == NULL || SQLITE_OK != rc) {
fprintf(stderr, Error: unable to open database: %s\n, sqlite3_errmsg(db));
exit(1);
}
sqlite3_create_function_v2(db, reuseAuxDataCountFunc, 1,
SQLITE_UTF8, 0, reuseAuxDataCountFunc, NULL, NULL, NULL);
// at least, one constant must be passed to make SQLite reuse auxiliary data...
  rc = sqlite3_prepare_v2(db, select reuseAuxDataCountFunc('test')
from (select 1 union all select 2), -1, stmt, NULL);
  if (stmt == NULL || SQLITE_OK != rc) {
fprintf(stderr, Error: prepare stmt: %s\n, sqlite3_errmsg(db));
exit(1);
  }
  for (int i = 1; i = 2; i++) {
  printf(loop %d\n, i);
 rc = sqlite3_step(stmt);
 while (rc == SQLITE_ROW) {
  z = (const char*)sqlite3_column_text(stmt, 0);
  printf(%s\n, z);
  rc = sqlite3_step(stmt);
 }
 if (SQLITE_OK != rc  SQLITE_DONE != rc) {
fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
exit(1);
}
 rc = sqlite3_reset(stmt);
 if (SQLITE_OK != rc) {
fprintf(stderr, Error: %s\n, sqlite3_errmsg(db));
exit(1);
}
}
  sqlite3_finalize(stmt);
sqlite3_close(db);
}

sqlite-amalgamation-3071700 gwen$ ./auxdata
loop 1
0
1
loop 2
2
3

sqlite-amalgamation-3080300 gwen$ ./auxdata
loop 1
0
1
loop 2
0
1

But it appears that SQLite is behaving as specified in:
http://sqlite.org/c3ref/get_auxdata.html
SQLite is free to discard the metadata at any time, including:
...
when sqlite3_reset() or sqlite3_finalize() is called for the SQL statement, or
...


Sorry for the false alarm.
I will try to find another strategy to keep the compiled regexp...
Regards.

On Sun, Feb 9, 2014 at 7:34 PM, Richard Hipp d...@sqlite.org wrote:
 Can you provide an example program that omits the glib.h dependency?


 On Sun, Feb 9, 2014 at 10:50 AM, gwenn gwenn.k...@gmail.com wrote:

 Hello,
 I am not sure but it seems there is a regression between versions
 3.7.17 and 3.8.0.
 It's impacting custom/user declared function and auxiliary data.

 sqlite-amalgamation-3071700 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3071700 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) reusing...
 z
 (0) reusing...
 y

 sqlite-amalgamation-3080300 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3080300 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) compiling...
 z
 (0) reusing...
 y

 The auxiliary data is reused in the second loop with SQLite 3.7.17 but
 not with SQLite 3.8.0.
 What is the expected/correct behaviour?

 Regards

 Here is the content of auxdata.c:
 #include stdlib.h
 #include stdio.h
 #include glib.h
 #include sqlite3.h

 static void log(void *pArg, int iErrCode, const char *zMsg) {
 printf((%d) %s\n, iErrCode, zMsg);
 }

 static void glibRegexpDelete(void *p){
   GRegex *pRegex = (GRegex *)p;
   g_regex_unref(pRegex);
 }

 static void glibReplaceAllFunc(
   sqlite3_context *ctx,
   int argc,
   sqlite3_value **argv
 ){
 GError *err = NULL;
 GRegex *p;
 gchar *result = NULL;

 (void)argc;  /* Unused parameter */

 const gchar *str = (const gchar *) sqlite3_value_text(argv[1]);
 if (!str) {
 return;
 }

 const gchar *replacement = (const gchar *) sqlite3_value_text(argv[2]);
 if (!replacement) {
 sqlite3_result_error(ctx, no replacement string, -1);
 return;
 }

 p = sqlite3_get_auxdata(ctx, 0);
 if( !p ){
 const gchar *re = (const gchar *) sqlite3_value_text(argv[0]);
 if( !re ){
 //sqlite3_result_error(ctx, no regexp, -1);
 return;
 }
 p = g_regex_new(re, 0, 0, err);

 if( p ){
 sqlite3_set_auxdata(ctx, 0, p, glibRegexpDelete);
 }else{
 char *e2 = sqlite3_mprintf(%s: %s, re, err-message);
 sqlite3_result_error(ctx, e2, -1);
 sqlite3_free(e2);
 g_error_free(err);
 return;
 }
 sqlite3_log(0, compiling...);
 } else {
 sqlite3_log(0, reusing...);
 }

 result = g_regex_replace(p, str, -1, 0, replacement, 0, err);
 if (err) {
 

Re: [sqlite] Different behaviour of auxiliary data between 3.7.17 and 3.8.0

2014-02-09 Thread Richard Hipp
This behavior change is in response to ticket
http://www.sqlite.org/src/info/406d3b2ef9 - a diff across several check-ins
that makes this change can be seen here:


http://www.sqlite.org/src/vdiff?from=b1b0de29fdf7de83to=62465ecba7431e1dsbs=1dc=25

Note that the behavior changes brings the implementation into agreement
with the historical documentation.  The document was clarified and enhanced
as part of this change.  But the key statements in the old documentation
where:

If [the sqlite3_set_auxdata destructor] is not NULL, SQLite will invoke
the destructor function given by the 4th parameter to sqlite3_set_auxdata()
on the metadata when the corresponding function parameter changes or when
the SQL statement completes, whichever comes first. SQLite is free to call
the destructor and drop metadata on any parameter of any function at any
time. The only guarantee is that the destructor will be called before the
metadata is dropped.

The corresponding text in the revised documentation is similar:

SQLite is free to discard the metadata at any time, including:
  *  when the corresponding function parameter changes, or
  * when [sqlite3_reset()] or [sqlite3_finalize()] is called for the  SQL
statement, or
  * when sqlite3_set_auxdata() is invoked again on the same parameter, or
  * during the original sqlite3_set_auxdata() call when a memory
allocation error occurs. 

The revised documentation is on the website here:
http://www.sqlite.org/c3ref/get_auxdata.html

So as far as I can tell, the current implementation is doing what it is
suppose to do. Or did I misunderstand the complaint?





On Sun, Feb 9, 2014 at 10:50 AM, gwenn gwenn.k...@gmail.com wrote:

 Hello,
 I am not sure but it seems there is a regression between versions
 3.7.17 and 3.8.0.
 It's impacting custom/user declared function and auxiliary data.

 sqlite-amalgamation-3071700 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3071700 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) reusing...
 z
 (0) reusing...
 y

 sqlite-amalgamation-3080300 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3080300 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) compiling...
 z
 (0) reusing...
 y

 The auxiliary data is reused in the second loop with SQLite 3.7.17 but
 not with SQLite 3.8.0.
 What is the expected/correct behaviour?

 Regards

 Here is the content of auxdata.c:
 #include stdlib.h
 #include stdio.h
 #include glib.h
 #include sqlite3.h

 static void log(void *pArg, int iErrCode, const char *zMsg) {
 printf((%d) %s\n, iErrCode, zMsg);
 }

 static void glibRegexpDelete(void *p){
   GRegex *pRegex = (GRegex *)p;
   g_regex_unref(pRegex);
 }

 static void glibReplaceAllFunc(
   sqlite3_context *ctx,
   int argc,
   sqlite3_value **argv
 ){
 GError *err = NULL;
 GRegex *p;
 gchar *result = NULL;

 (void)argc;  /* Unused parameter */

 const gchar *str = (const gchar *) sqlite3_value_text(argv[1]);
 if (!str) {
 return;
 }

 const gchar *replacement = (const gchar *) sqlite3_value_text(argv[2]);
 if (!replacement) {
 sqlite3_result_error(ctx, no replacement string, -1);
 return;
 }

 p = sqlite3_get_auxdata(ctx, 0);
 if( !p ){
 const gchar *re = (const gchar *) sqlite3_value_text(argv[0]);
 if( !re ){
 //sqlite3_result_error(ctx, no regexp, -1);
 return;
 }
 p = g_regex_new(re, 0, 0, err);

 if( p ){
 sqlite3_set_auxdata(ctx, 0, p, glibRegexpDelete);
 }else{
 char *e2 = sqlite3_mprintf(%s: %s, re, err-message);
 sqlite3_result_error(ctx, e2, -1);
 sqlite3_free(e2);
 g_error_free(err);
 return;
 }
 sqlite3_log(0, compiling...);
 } else {
 sqlite3_log(0, reusing...);
 }

 result = g_regex_replace(p, str, -1, 0, replacement, 0, err);
 if (err) {
 sqlite3_result_error(ctx, err-message, -1);
 g_error_free(err);
 return;
 }
 sqlite3_result_text(ctx, result, -1, g_free);
 }

 int main(int argc, char **argv) {
 sqlite3_config(SQLITE_CONFIG_LOG, log, NULL);
 sqlite3 *db = NULL;
 sqlite3_stmt *stmt = NULL;
 char *zErrMsg = NULL;
 const char *z;
 int rc = 0;
 rc = sqlite3_open_v2(:memory:, db, SQLITE_OPEN_FULLMUTEX |
 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
 if (db == NULL || SQLITE_OK != rc) {
 fprintf(stderr, Error: unable to open database: %s\n,
 sqlite3_errmsg(db));
 exit(1);
 }
 sqlite3_create_function_v2(db, regex_replace, 3, SQLITE_UTF8, 0,
 glibReplaceAllFunc, NULL, NULL, NULL);
   rc = sqlite3_prepare_v2(db, select regex_replace('.', 'abcde', r)
 from (select 'z' as r union all select 'y'), -1, stmt, NULL);
   if (stmt == NULL || SQLITE_OK != rc) {
 fprintf(stderr, Error: prepare stmt: %s\n, sqlite3_errmsg(db));
 exit(1);
   }
   for 

Re: [sqlite] Different behaviour of auxiliary data between 3.7.17 and 3.8.0

2014-02-09 Thread gwenn
Yes, you are right.
Thanks for the investigation.


On Sun, Feb 9, 2014 at 11:54 PM, Richard Hipp d...@sqlite.org wrote:
 This behavior change is in response to ticket
 http://www.sqlite.org/src/info/406d3b2ef9 - a diff across several check-ins
 that makes this change can be seen here:


 http://www.sqlite.org/src/vdiff?from=b1b0de29fdf7de83to=62465ecba7431e1dsbs=1dc=25

 Note that the behavior changes brings the implementation into agreement
 with the historical documentation.  The document was clarified and enhanced
 as part of this change.  But the key statements in the old documentation
 where:

 If [the sqlite3_set_auxdata destructor] is not NULL, SQLite will invoke
 the destructor function given by the 4th parameter to sqlite3_set_auxdata()
 on the metadata when the corresponding function parameter changes or when
 the SQL statement completes, whichever comes first. SQLite is free to call
 the destructor and drop metadata on any parameter of any function at any
 time. The only guarantee is that the destructor will be called before the
 metadata is dropped.

 The corresponding text in the revised documentation is similar:

 SQLite is free to discard the metadata at any time, including:
   *  when the corresponding function parameter changes, or
   * when [sqlite3_reset()] or [sqlite3_finalize()] is called for the  SQL
 statement, or
   * when sqlite3_set_auxdata() is invoked again on the same parameter, or
   * during the original sqlite3_set_auxdata() call when a memory
 allocation error occurs. 

 The revised documentation is on the website here:
 http://www.sqlite.org/c3ref/get_auxdata.html

 So as far as I can tell, the current implementation is doing what it is
 suppose to do. Or did I misunderstand the complaint?





 On Sun, Feb 9, 2014 at 10:50 AM, gwenn gwenn.k...@gmail.com wrote:

 Hello,
 I am not sure but it seems there is a regression between versions
 3.7.17 and 3.8.0.
 It's impacting custom/user declared function and auxiliary data.

 sqlite-amalgamation-3071700 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3071700 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) reusing...
 z
 (0) reusing...
 y

 sqlite-amalgamation-3080300 gwen$ gcc
 -I/usr/local/Cellar/glib/2.38.2/include/glib-2.0
 -I/usr/local/Cellar/glib/2.38.2/lib/glib-2.0/include sqlite3.c
 auxdata.c -o auxdata -L/usr/local/Cellar/glib/2.38.2/lib -lglib-2.0
 sqlite-amalgamation-3080300 gwen$ ./auxdata
 loop 1
 (0) compiling...
 z
 (0) reusing...
 y
 loop 2
 (0) compiling...
 z
 (0) reusing...
 y

 The auxiliary data is reused in the second loop with SQLite 3.7.17 but
 not with SQLite 3.8.0.
 What is the expected/correct behaviour?

 Regards

 Here is the content of auxdata.c:
 #include stdlib.h
 #include stdio.h
 #include glib.h
 #include sqlite3.h

 static void log(void *pArg, int iErrCode, const char *zMsg) {
 printf((%d) %s\n, iErrCode, zMsg);
 }

 static void glibRegexpDelete(void *p){
   GRegex *pRegex = (GRegex *)p;
   g_regex_unref(pRegex);
 }

 static void glibReplaceAllFunc(
   sqlite3_context *ctx,
   int argc,
   sqlite3_value **argv
 ){
 GError *err = NULL;
 GRegex *p;
 gchar *result = NULL;

 (void)argc;  /* Unused parameter */

 const gchar *str = (const gchar *) sqlite3_value_text(argv[1]);
 if (!str) {
 return;
 }

 const gchar *replacement = (const gchar *) sqlite3_value_text(argv[2]);
 if (!replacement) {
 sqlite3_result_error(ctx, no replacement string, -1);
 return;
 }

 p = sqlite3_get_auxdata(ctx, 0);
 if( !p ){
 const gchar *re = (const gchar *) sqlite3_value_text(argv[0]);
 if( !re ){
 //sqlite3_result_error(ctx, no regexp, -1);
 return;
 }
 p = g_regex_new(re, 0, 0, err);

 if( p ){
 sqlite3_set_auxdata(ctx, 0, p, glibRegexpDelete);
 }else{
 char *e2 = sqlite3_mprintf(%s: %s, re, err-message);
 sqlite3_result_error(ctx, e2, -1);
 sqlite3_free(e2);
 g_error_free(err);
 return;
 }
 sqlite3_log(0, compiling...);
 } else {
 sqlite3_log(0, reusing...);
 }

 result = g_regex_replace(p, str, -1, 0, replacement, 0, err);
 if (err) {
 sqlite3_result_error(ctx, err-message, -1);
 g_error_free(err);
 return;
 }
 sqlite3_result_text(ctx, result, -1, g_free);
 }

 int main(int argc, char **argv) {
 sqlite3_config(SQLITE_CONFIG_LOG, log, NULL);
 sqlite3 *db = NULL;
 sqlite3_stmt *stmt = NULL;
 char *zErrMsg = NULL;
 const char *z;
 int rc = 0;
 rc = sqlite3_open_v2(:memory:, db, SQLITE_OPEN_FULLMUTEX |
 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
 if (db == NULL || SQLITE_OK != rc) {
 fprintf(stderr, Error: unable to open database: %s\n,
 sqlite3_errmsg(db));
 exit(1);
 }
 sqlite3_create_function_v2(db, regex_replace, 3, SQLITE_UTF8, 0,
 glibReplaceAllFunc, NULL, NULL, NULL);
   rc = sqlite3_prepare_v2(db, select regex_replace('.', 'abcde', r)
 from (select 'z' as r union all select