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  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=b1b0de29fdf7de83=62465ecba7431e1d=1=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  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 
>> #include 
>> #include 
>> #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, );
>>
>> 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, );
>> 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:", , SQLITE_OPEN_FULLMUTEX |
>> SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
>> if (db == NULL || SQLITE_OK != rc) {
>> fprintf(stderr, "Error: 

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=b1b0de29fdf7de83=62465ecba7431e1d=1=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  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 
> #include 
> #include 
> #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, );
>
> 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, );
> 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:", , 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, , NULL);
>   if 

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

2014-02-09 Thread gwenn
Here you are:

#include 
#include 
#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:", , 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, , 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  wrote:
> Can you provide an example program that omits the glib.h dependency?
>
>
> On Sun, Feb 9, 2014 at 10:50 AM, gwenn  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 
>> #include 
>> #include 
>> #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, );
>>
>> 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);
>> 

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  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 
> #include 
> #include 
> #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, );
>
> 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, );
> 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:", , 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, , 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


[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 
#include 
#include 
#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, );

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, );
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:", , 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, , 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