PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
Hi, Below follows a series of 12 patches against Guile-DBI and DBD-Postgres. Guile DBI is a wrapper for accessing SQL databases. https://gna.org/projects/guile-dbi/ I'm posting here -- although there used to be guile-dbi-user and guile-dbi-devel mailing lists, these had no subscribers, and quickly filled with spam, as evidenced by their mail archives. I've applied to get an account on gna.org to post the patches there, but its been a week, and my account application still hasn't gone through :-( It also appears that the original maintainer, Maurizio Boriani, is not responding to email. Bummer. The patches fix a variety of different crashes and hangs, and also fix problems with missing data (e.g. for a query with N records, only N-1 were being returned -- bad news when N=1) --linas
[PATCH 1/12] Guile-DBI: Avoid multiple init
If (use-modules (dbi dbi)) is called multiple times, then guile will crash in various strange ways, often during garbage-collection. Thus, avoid initializaing more than once. From: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbi.c |3 +++ 1 file changed, 3 insertions(+) Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-15 13:03:05.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-15 13:19:36.0 -0500 @@ -295,6 +295,9 @@ init_db_handle_type(void) void init_dbi(void) { + static int is_inited = 0; + if (is_inited) return; + is_inited = 1; init_db_handle_type(); #ifndef SCM_MAGIC_SNARFER signature.asc Description: Digital signature
[PATCH 2/12] Guile-DBI: minor cleanup
Minor cleanup: -- avoid forward decarations -- rename confusingly named function -- free function should return zero, per current guile specs. -- remove deprecated header -- fix typo Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- include/guile-dbi/guile-dbi.h | 10 +++--- src/guile-dbi.c | 14 -- 2 files changed, 7 insertions(+), 17 deletions(-) Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 17:26:58.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 19:54:42.0 -0500 @@ -29,11 +29,6 @@ static scm_t_bits g_db_handle_tag; -static SCM mark_db_handle (SCM g_db_handle_smob); -static size_t free_db_handle (SCM g_db_handle_smob); -static int print_db_handle (SCM g_db_handle_smob, SCM port, - scm_print_state* pstate); - #define DBI_SMOB_P(obj) ((SCM_NIMP(obj)) && (SCM_TYP16(obj)==g_db_handle_tag)) @@ -154,7 +149,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos #define FUNC_NAME s_close_db_handle { struct g_db_handle *g_db_handle = NULL; - void (*dbi_close)(gdbi_db_handle_t*); + void (*dbd_close)(gdbi_db_handle_t*); SCM_ASSERT (DBI_SMOB_P(db_handle), db_handle, SCM_ARG1, "close_g_db_handle"); g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); @@ -164,12 +159,12 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos return SCM_UNSPECIFIED; } - __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_close); + __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbd_close); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { return SCM_UNSPECIFIED; } - (*dbi_close)(g_db_handle); + (*dbd_close)(g_db_handle); if (g_db_handle->handle) { dlclose(g_db_handle->handle); @@ -185,7 +180,6 @@ static size_t free_db_handle (SCM g_db_handle_smob) { struct g_db_handle *g_db_handle = NULL; - size_t size = sizeof(struct g_db_handle); g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(g_db_handle_smob); close_g_db_handle(g_db_handle_smob); @@ -196,7 +190,7 @@ free_db_handle (SCM g_db_handle_smob) } SCM_SETCDR (g_db_handle_smob, (SCM)NULL); - return (size); + return 0; } Index: guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h === --- guile-dbi-2.0.0.orig/include/guile-dbi/guile-dbi.h 2008-09-16 19:03:18.0 -0500 +++ guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h 2008-09-16 19:53:09.0 -0500 @@ -17,17 +17,13 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * Process this file with autoconf to produce a configure script. */ + */ #ifndef __GUILE_DBI_H__ #define __GUILE_DBI_H__ - #include -#include - /* guile smob struct */ typedef struct g_db_handle @@ -50,8 +46,8 @@ void init_dbi(void); -/* dbd dynamyc wrapper stuff */ +/* dbd dynamic wrapper stuff */ void __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, char* function_name, void** function_pointer); -/* end dbd dynamyc wrapper stuff */ +/* end dbd dynamic wrapper stuff */ #endif signature.asc Description: Digital signature
[PATCH 3/12] Guile-DBI: Fix memory leak
Fix memory leak; various allocated strins are not freed in assorted error paths. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbi.c |7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 20:52:25.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 20:53:13.0 -0500 @@ -55,12 +55,13 @@ SCM_DEFINE (make_g_db_handle, "dbi-open" g_db_handle->handle = NULL; g_db_handle->db_info = NULL; - bcknd_str = (char*) gh_scm2newstr(bcknd,NULL); + bcknd_str = scm_to_locale_string (bcknd); sodbd=(char*) malloc (sizeof(char)*(strlen("libguile-dbd-") + strlen(bcknd_str) + 10)); if (sodbd == NULL) { + free(bcknd_str); g_db_handle->status = scm_cons(scm_from_int(errno), scm_makfrom0str(strerror(errno))); SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle); @@ -70,6 +71,8 @@ SCM_DEFINE (make_g_db_handle, "dbi-open" g_db_handle->handle = dlopen(sodbd,RTLD_NOW); if ( g_db_handle->handle == NULL) { + free(bcknd_str); + free(sodbd); g_db_handle->status = scm_cons(scm_from_int(1), scm_makfrom0str(dlerror())); SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle); @@ -78,6 +81,8 @@ SCM_DEFINE (make_g_db_handle, "dbi-open" __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &connect); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { + free(bcknd_str); + free(sodbd); SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle); } signature.asc Description: Digital signature
[PATCH 4/12] Guile-DBII: replace deprecated gh_ functions
Replace deprecated gh_ functions with modern scm_ functions Also, another memory leak. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbi.c |6 -- 1 file changed, 4 insertions(+), 2 deletions(-) Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 18:44:31.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 18:47:11.0 -0500 @@ -214,7 +214,7 @@ SCM_DEFINE (query_g_db_handle, "dbi-quer SCM_ASSERT (scm_is_string (query), query, SCM_ARG2, "query_g_db_handle"); g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); - query_str = (char*) gh_scm2newstr(query,NULL); + query_str = scm_to_locale_string(query); __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_query); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) @@ -315,11 +315,12 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c char *func = NULL; char *bcknd = NULL; - bcknd = (char*) gh_scm2newstr(dbh->bcknd,NULL); + bcknd = scm_to_locale_string(dbh->bcknd); if((func=malloc(sizeof(char)*(strlen(function_name)+ 20))) == NULL) { + free(bcknd); dbh->status = (SCM) scm_cons(scm_from_int(errno), scm_makfrom0str(strerror(errno))); return; @@ -329,6 +330,7 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c *(void **) (function_pointer) = dlsym(dbh->handle,func); if((ret = dlerror()) != NULL) { + free(bcknd); dbh->status = (SCM) scm_cons(scm_from_int(1), scm_makfrom0str(ret)); return; signature.asc Description: Digital signature
[PATCH 6/12] Guile-DBI: Fix crash, avoid recursive free
There is a particularly nasty crash scenario invloving the garbage collector. The problem is that the dbi free routine calls the dbi close routine, which tries to alloc new SCM nodes. This is bad, because one should not alloc while the garbage collector is running. So add a flag, incidating that a free is in progress. The DBD layers will have to honour this flag. (also fixes one more mem leak). Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- include/guile-dbi/guile-dbi.h |1 + src/guile-dbi.c | 14 -- 2 files changed, 13 insertions(+), 2 deletions(-) Index: guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h === --- guile-dbi-2.0.0.orig/include/guile-dbi/guile-dbi.h 2008-09-16 21:36:22.0 -0500 +++ guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h 2008-09-16 21:40:30.0 -0500 @@ -34,6 +34,7 @@ typedef struct g_db_handle SCM closed; /* boolean, TRUE if closed otherwise FALSE */ void* handle; void* db_info; + int in_free; } gdbi_db_handle_t; /* end guile smob struct */ Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 21:40:24.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 21:40:30.0 -0500 @@ -53,6 +53,8 @@ SCM_DEFINE (make_g_db_handle, "dbi-open" g_db_handle->bcknd = bcknd; g_db_handle->constr = conn_string; g_db_handle->handle = NULL; + g_db_handle->closed = SCM_BOOL_T; + g_db_handle->in_free = 0; g_db_handle->db_info = NULL; bcknd_str = scm_to_locale_string (bcknd); @@ -189,6 +191,9 @@ free_db_handle (SCM g_db_handle_smob) struct g_db_handle *g_db_handle = NULL; g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(g_db_handle_smob); + if (g_db_handle->in_free) return 0; + g_db_handle->in_free = 1; + close_g_db_handle(g_db_handle_smob); if (g_db_handle != NULL) @@ -325,7 +330,8 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c 20))) == NULL) { free(bcknd); - dbh->status = (SCM) scm_cons(scm_from_int(errno), + if (dbh->in_free) return; /* do not SCM anything while in GC */ + dbh->status = scm_cons(scm_from_int(errno), scm_makfrom0str(strerror(errno))); return; } @@ -335,6 +341,8 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c if((ret = dlerror()) != NULL) { free(bcknd); + free(func); + if (dbh->in_free) return; /* do not SCM anything while in GC */ dbh->status = (SCM) scm_cons(scm_from_int(1), scm_makfrom0str(ret)); return; @@ -345,8 +353,10 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c { free(bcknd); } + + if (dbh->in_free) return; /* do not SCM anything while in GC */ /* todo: error msg to be translated */ - dbh->status = (SCM) scm_cons(scm_from_int(0), + dbh->status = scm_cons(scm_from_int(0), scm_makfrom0str("symbol loaded")); return; } signature.asc Description: Digital signature
[PATCH 5/12] Guile-DBI: Use remember_upto_here
Sprinkle code with some scm_remember_upto_here_1(), as it looks like there's a potential garbage-collection race. Also, simplify a particularly complicated test. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbi.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 20:53:23.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 21:40:24.0 -0500 @@ -159,7 +159,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos SCM_ASSERT (DBI_SMOB_P(db_handle), db_handle, SCM_ARG1, "close_g_db_handle"); g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); - if (scm_equal_p (g_db_handle->closed, SCM_BOOL_T) == SCM_BOOL_T) + if (g_db_handle->closed == SCM_BOOL_T) { return SCM_UNSPECIFIED; } @@ -167,6 +167,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbd_close); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { + scm_remember_upto_here_1(db_handle); return SCM_UNSPECIFIED; } (*dbd_close)(g_db_handle); @@ -175,6 +176,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos dlclose(g_db_handle->handle); g_db_handle->handle = NULL; } + scm_remember_upto_here_1(db_handle); return SCM_UNSPECIFIED; } #undef FUNC_NAME @@ -217,13 +219,13 @@ SCM_DEFINE (query_g_db_handle, "dbi-quer query_str = scm_to_locale_string(query); __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_query); - if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) + if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_T) { - return(SCM_UNSPECIFIED); + (*dbi_query)(g_db_handle,query_str); } - - (*dbi_query)(g_db_handle,query_str); + free(query_str); + scm_remember_upto_here_1(db_handle); return (SCM_UNSPECIFIED); } #undef FUNC_NAME @@ -240,17 +242,18 @@ SCM_DEFINE (getrow_g_db_handle, "dbi-get SCM (*dbi_getrow)(gdbi_db_handle_t*); SCM_ASSERT (DBI_SMOB_P(db_handle), db_handle, SCM_ARG1, "getrow_g_db_handle"); - g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_getrow); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { + scm_remember_upto_here_1(db_handle); return(retrow); } retrow = (*dbi_getrow)(g_db_handle); + scm_remember_upto_here_1(db_handle); return(retrow); } #undef FUNC_NAME @@ -270,6 +273,7 @@ SCM_DEFINE (getstat_g_db_handle, "dbi-ge if (g_db_handle != NULL) { + scm_remember_upto_here_1(db_handle); return (g_db_handle->status); } signature.asc Description: Digital signature
[PATCH 7/12] Guile-DBI: Don't cast away const
Avoid casting away const. Actually, avoid casting. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- include/guile-dbi/guile-dbi.h |2 +- src/guile-dbi.c | 15 +++ 2 files changed, 8 insertions(+), 9 deletions(-) Index: guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h === --- guile-dbi-2.0.0.orig/include/guile-dbi/guile-dbi.h 2008-09-16 21:40:30.0 -0500 +++ guile-dbi-2.0.0/include/guile-dbi/guile-dbi.h 2008-09-16 21:40:43.0 -0500 @@ -48,7 +48,7 @@ void init_dbi(void); /* dbd dynamic wrapper stuff */ -void __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, char* function_name, +void __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, const char* function_name, void** function_pointer); /* end dbd dynamic wrapper stuff */ #endif Index: guile-dbi-2.0.0/src/guile-dbi.c === --- guile-dbi-2.0.0.orig/src/guile-dbi.c2008-09-16 21:40:30.0 -0500 +++ guile-dbi-2.0.0/src/guile-dbi.c 2008-09-16 21:42:31.0 -0500 @@ -80,7 +80,7 @@ SCM_DEFINE (make_g_db_handle, "dbi-open" SCM_RETURN_NEWSMOB (g_db_handle_tag, g_db_handle); } - __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &connect); + __gdbi_dbd_wrap(g_db_handle, __FUNCTION__,(void**) &connect); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { free(bcknd_str); @@ -166,7 +166,7 @@ SCM_DEFINE (close_g_db_handle, "dbi-clos return SCM_UNSPECIFIED; } - __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbd_close); + __gdbi_dbd_wrap(g_db_handle, __FUNCTION__,(void**) &dbd_close); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { scm_remember_upto_here_1(db_handle); @@ -223,7 +223,7 @@ SCM_DEFINE (query_g_db_handle, "dbi-quer g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); query_str = scm_to_locale_string(query); - __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_query); + __gdbi_dbd_wrap(g_db_handle, __FUNCTION__,(void**) &dbi_query); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_T) { (*dbi_query)(g_db_handle,query_str); @@ -249,7 +249,7 @@ SCM_DEFINE (getrow_g_db_handle, "dbi-get SCM_ASSERT (DBI_SMOB_P(db_handle), db_handle, SCM_ARG1, "getrow_g_db_handle"); g_db_handle = (struct g_db_handle*)SCM_SMOB_DATA(db_handle); - __gdbi_dbd_wrap(g_db_handle,(char*) __FUNCTION__,(void**) &dbi_getrow); + __gdbi_dbd_wrap(g_db_handle, __FUNCTION__,(void**) &dbi_getrow); if (scm_equal_p (SCM_CAR(g_db_handle->status),scm_from_int(0)) == SCM_BOOL_F) { scm_remember_upto_here_1(db_handle); @@ -317,7 +317,7 @@ init_dbi(void) /* dbd handler */ void -__gdbi_dbd_wrap(gdbi_db_handle_t* dbh, char* function_name, +__gdbi_dbd_wrap(gdbi_db_handle_t* dbh, const char* function_name, void** function_pointer) { char *ret = NULL; @@ -337,13 +337,13 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c } sprintf(func,"__%s_%s",bcknd,function_name); - *(void **) (function_pointer) = dlsym(dbh->handle,func); + *function_pointer = dlsym(dbh->handle,func); if((ret = dlerror()) != NULL) { free(bcknd); free(func); if (dbh->in_free) return; /* do not SCM anything while in GC */ - dbh->status = (SCM) scm_cons(scm_from_int(1), + dbh->status = scm_cons(scm_from_int(1), scm_makfrom0str(ret)); return; } @@ -358,5 +358,4 @@ __gdbi_dbd_wrap(gdbi_db_handle_t* dbh, c /* todo: error msg to be translated */ dbh->status = scm_cons(scm_from_int(0), scm_makfrom0str("symbol loaded")); - return; } signature.asc Description: Digital signature
[PATCH 8/12] Guile-DBD-postgres: Fix handling of float point columns
Database columns containing floating point and double values are not handled correctly; they are handled as ints. Fix this. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbd-postgresql.c |9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) Index: guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c === --- guile-dbd-postgresql-2.0.0.orig/src/guile-dbd-postgresql.c 2008-09-15 10:22:59.0 -0500 +++ guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c 2008-09-15 10:33:54.0 -0500 @@ -311,8 +311,6 @@ __postgresql_getrow_g_db_handle(gdbi_db_ SCM value; int type = PQftype(pgsqlP->res,f); if ((type >= 20 && type <= 24) || - type == 700|| - type == 701|| type == 1700 || type == 26 ) { @@ -320,6 +318,13 @@ __postgresql_getrow_g_db_handle(gdbi_db_ PQgetlength(pgsqlP->res,pgsqlP->lget,f)); value = scm_int2num(atoi(value_str)); } + else if (type == 700 || + type == 701) + { + value_str = (char*) strndup(PQgetvalue(pgsqlP->res,pgsqlP->lget,f), + PQgetlength(pgsqlP->res,pgsqlP->lget,f)); + value = scm_from_double(atof(value_str)); + } else if (type == 18 || type == 19 || type == 25 || signature.asc Description: Digital signature
[PATCH 9/12] Guile-DBD-postgres: Avoid discouraged functions
Don't use functions from the guile "discouraged" header. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbd-postgresql.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c === --- guile-dbd-postgresql-2.0.0.orig/src/guile-dbd-postgresql.c 2008-09-15 10:45:02.0 -0500 +++ guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c 2008-09-15 13:24:54.0 -0500 @@ -316,7 +316,7 @@ __postgresql_getrow_g_db_handle(gdbi_db_ { value_str = (char*) strndup(PQgetvalue(pgsqlP->res,pgsqlP->lget,f), PQgetlength(pgsqlP->res,pgsqlP->lget,f)); - value = scm_int2num(atoi(value_str)); + value = scm_from_long(atoi(value_str)); } else if (type == 700 || type == 701) signature.asc Description: Digital signature
[PATCH 10/12] Guile-DBD-postgres: Fix off-by-one when fetching rows
It appears that the current postgres dbd code will return one less row than the database actually contains, which is a disaster if the database holds only one row! Fix this. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbd-postgresql.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c === --- guile-dbd-postgresql-2.0.0.orig/src/guile-dbd-postgresql.c 2008-09-15 14:10:33.0 -0500 +++ guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c 2008-09-15 14:11:02.0 -0500 @@ -299,7 +299,7 @@ __postgresql_getrow_g_db_handle(gdbi_db_ pgsqlP->lget = 0; return (SCM_BOOL_F); } - else if (pgsqlP->lget == (PQntuples(pgsqlP->res) - 1)) + else if (pgsqlP->lget == PQntuples(pgsqlP->res)) { pgsqlP->res = PQgetResult(pgsqlP->pgsql); } signature.asc Description: Digital signature
[PATCH 11/12] Guile-DBD-postgres: Avoid deprecated functions
Don't use deprecated guile gh_ functions. Also, move some string handling functions around so as to avoid memory leak. Also, avoid some casting. Casting is bad, it can hide errors from the compiler. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbd-postgresql.c | 67 ++--- 1 file changed, 34 insertions(+), 33 deletions(-) Index: guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c === --- guile-dbd-postgresql-2.0.0.orig/src/guile-dbd-postgresql.c 2008-09-16 19:31:37.0 -0500 +++ guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c 2008-09-16 19:46:13.0 -0500 @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -59,7 +58,7 @@ __postgresql_make_g_db_handle(gdbi_db_ha if(scm_equal_p(scm_string_p(dbh->constr), SCM_BOOL_F) == SCM_BOOL_T) { /* todo: error msg to be translated */ - dbh->status = (SCM) scm_cons(scm_from_int(1), + dbh->status = scm_cons(scm_from_int(1), scm_from_locale_string("missing connection string")); return; } @@ -70,11 +69,7 @@ __postgresql_make_g_db_handle(gdbi_db_ha if (items >= 5 && items < 8) { char* port = NULL; - char* user = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(0)),NULL); - char* pass = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(1)),NULL); - char* db = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(2)),NULL); - char* ctyp = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(3)),NULL); - char* loc = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(4)),NULL); + char* user, *pass, *db, *ctyp, *loc; pgsqlP = (gdbi_pgsql_ds_t*)malloc(sizeof(gdbi_pgsql_ds_t)); pgsqlP->retn = 0; @@ -86,18 +81,24 @@ __postgresql_make_g_db_handle(gdbi_db_ha return; } + user = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(0))); + pass = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(1))); + db = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(2))); + ctyp = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(3))); + loc = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(4))); + pgsqlP->pgsql = NULL; pgsqlP->res = NULL; if (strcmp(ctyp,"tcp") == 0) { - port = (char*) gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(5)),NULL); + port = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(5))); pgsqlP->pgsql = (PGconn*) PQsetdbLogin(loc,port,NULL,NULL,db,user,pass); if (items == 7) { - char* sretn = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(6)), - NULL); + char* sretn = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(6))); pgsqlP->retn = atoi(sretn); + free (sretn); } } else @@ -105,9 +106,9 @@ __postgresql_make_g_db_handle(gdbi_db_ha pgsqlP->pgsql = (PGconn*) PQsetdbLogin(loc,NULL,NULL,NULL,db,user,pass); if (items == 6) { - char* sretn = gh_scm2newstr(scm_list_ref(cp_list,scm_from_int(5)), - NULL); + char* sretn = scm_to_locale_string(scm_list_ref(cp_list,scm_from_int(5))); pgsqlP->retn = atoi(sretn); + free (sretn); } } @@ -139,7 +140,7 @@ __postgresql_make_g_db_handle(gdbi_db_ha if(PQstatus(pgsqlP->pgsql) == CONNECTION_BAD) { - dbh->status = (SCM) scm_cons(scm_from_int(1), + dbh->status = scm_cons(scm_from_int(1), scm_from_locale_string(PQerrorMessage(pgsqlP->pgsql))); PQfinish(pgsqlP->pgsql); pgsqlP->pgsql = NULL; @@ -151,7 +152,7 @@ __postgresql_make_g_db_handle(gdbi_db_ha else { /* todo: error msg to be translated */ - dbh->status = (SCM) scm_cons(scm_from_int(0), + dbh->status = scm_cons(scm_from_int(0), scm_from_locale_string("db connected")); dbh->db_info = pgsqlP; dbh->closed = SCM_BOOL_F; @@ -161,7 +162,7 @@ __postgresql_make_g_db_handle(gdbi_db_ha else { /* todo: error msg to be translated */ - dbh->status = (SCM) scm_cons(scm_from_int(1), + dbh->status = scm_cons(scm_from_int(1), scm_from_locale_string("invalid connection string")); dbh->db_info = NULL; dbh->closed = SCM_BOOL_T; @@ -181,14 +182,14 @@ __postgresql_close_g_db_handle(gdbi_db_h if (pgsqlP == NULL) { /* todo: error msg to be translated */ - dbh->status = (SCM) scm_cons(scm_from_int(1), + dbh->status = scm_cons(scm_from_int(1), scm_from_locale_str
[PATCH 12/12] Guile-DBD-postgres: Crash in GC
Fix a serious bug which results in a crash in the GC. The problem is that the DBI free routine ill call the close routine, which will call this routine, which tries to alloc new SCM cells. But one must not alloc while the garbage collector is runing. Soo.. A previous patch added a flag to indicate that we're in the GC. If this flag is set, then avoid doing the cell allocs. Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]> --- src/guile-dbd-postgresql.c | 14 ++ 1 file changed, 10 insertions(+), 4 deletions(-) Index: guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c === --- guile-dbd-postgresql-2.0.0.orig/src/guile-dbd-postgresql.c 2008-09-16 19:57:34.0 -0500 +++ guile-dbd-postgresql-2.0.0/src/guile-dbd-postgresql.c 2008-09-16 20:05:25.0 -0500 @@ -181,6 +181,7 @@ __postgresql_close_g_db_handle(gdbi_db_h gdbi_pgsql_ds_t* pgsqlP = (gdbi_pgsql_ds_t*)dbh->db_info; if (pgsqlP == NULL) { + if (dbh->in_free) return; /* don't scm anything if in GC */ /* todo: error msg to be translated */ dbh->status = scm_cons(scm_from_int(1), scm_from_locale_string("dbd info not found")); @@ -188,9 +189,12 @@ __postgresql_close_g_db_handle(gdbi_db_h } else if (pgsqlP->pgsql == NULL) { - /* todo: error msg to be translated */ - dbh->status = scm_cons(scm_from_int(1), - scm_from_locale_string("dbi connection already closed")); + if (0 == dbh->in_free) +{ + /* todo: error msg to be translated */ + dbh->status = scm_cons(scm_from_int(1), + scm_from_locale_string("dbi connection already closed")); +} free(dbh->db_info); dbh->db_info = NULL; dbh->closed = SCM_BOOL_T; @@ -207,8 +211,10 @@ __postgresql_close_g_db_handle(gdbi_db_h free(dbh->db_info); dbh->db_info = NULL; - /* todo: error msg to be translated */ dbh->closed = SCM_BOOL_T; + + if (dbh->in_free) return; /* don't scm anything if in GC */ + /* todo: error msg to be translated */ dbh->status = scm_cons(scm_from_int(0), scm_from_locale_string("dbi closed")); return; signature.asc Description: Digital signature
project page
hello i think guiles project page could need at least 2 small changes. 1 replace the link 'anonymous cvs' under 'getting guile' with one to the more up to date page, this one: http://www.gnu.org/software/guile/repository.html 2 that page says to use 'git-clone', which does not exist on my system, only 'git clone' works.
Re: PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
- Original Message > From: Linas Vepstas <[EMAIL PROTECTED]> > > Hi, > > Below follows a series of 12 patches against Guile-DBI and DBD-Postgres. > Linus, thank you for doing this. -Mike Gran
Re: project page
Hi, tantalum <[EMAIL PROTECTED]> writes: > 1 > replace the link 'anonymous cvs' under 'getting guile' with one to the > more up to date page, > this one: http://www.gnu.org/software/guile/repository.html > > 2 > that page says to use 'git-clone', which does not exist on my system, > only 'git clone' works. This is now fixed, thanks! Ludo'.
Re: PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
2008/9/19 Linas Vepstas <[EMAIL PROTECTED]>: > > I'm posting here -- although there used to be guile-dbi-user and > guile-dbi-devel > mailing lists, these had no subscribers, and quickly filled with spam, as > evidenced by their mail archives. I've applied to get an account on gna.org > to post the patches there, but its been a week, and my account application > still hasn't gone through :-( It also appears that the original maintainer, > Maurizio Boriani, is not responding to email. Bummer. Can anyone provide firm evidence regarding whether guile-dbi is now maintained or unmaintained? If it is unmaintained, I guess we could consider merging it into the core Guile distribution. Any thoughts on that? Also, can anyone provide a summary of all the DB-related libraries for Guile? I believe there's guile-pg, and guile-sqlite, but (i) there could be others I've forgotten, and (ii) it would be great if someone could summarize how they differ / overlap / compare with each other. > The patches fix a variety of different crashes and hangs, and also fix > problems with missing data (e.g. for a query with N records, only N-1 > were being returned -- bad news when N=1) Cool, thanks. If it turns out to make sense to pull guile-dbi into core Guile, I guess we'll review and incorporate these patches at that time. Regards, Neil
Re: PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
Also, can anyone provide a summary of all the DB-related libraries for Guile? I believe there's guile-pg, and guile-sqlite, but (i) there could be others I've forgotten, and (ii) it would be great if someone could summarize how they differ / overlap / compare with each other. I am familiar with guile-pg. It used to be on sourceforge, and was unmaintained, and then ttn took it over and has done a lot of work on it. Last I checked guile-pg only supported guile through 1.6 due to it using hte load-module-from-.so feature removed in 1.8, but ttn has said that he'd take patches to make guile-pg work with 1.8+. There is ttn's guile-gdbm: http://www.gnuvola.org/software/guile-gdbm/ There is no guile-dbi package in pkgsrc. I dimly remember a pg-guile which was BSD licensed but have not heard anything about it in years. pgp1p3DHLcgd6.pgp Description: PGP signature
Re: PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
Also, can anyone provide a summary of all the DB-related libraries for Guile? I believe there's guile-pg, and guile-sqlite, but (i) there could be others I've forgotten, and (ii) it would be great if someone could summarize how they differ / overlap / compare with each other. guile-pg has really nice support for converting postgresql types to and From scheme types, and you can register custom converters. So it's much beyond just being able to run query strings and get string answers. I have the impression that it's implementation is tied to pg. IMHO the right thing would be to use the type mapping part of guile-pg with a DBI sort of back end to go to various databases. pgpu9IsYGo5hu.pgp Description: PGP signature
Re: PATCH [0/12]: Guile-DBI and Guile-DBD-Postgres
2008/9/19 Greg Troxel <[EMAIL PROTECTED]>: > > guile-pg has really nice support for converting postgresql types to and > From scheme types, ? I would be surprised if any database interface returned a string, when the database column was declared an int, so I don't quite understand this ... > and you can register custom converters. This could be interesting. Different databases have all sorts of crazy column formats (23 different types of dates, money amounts, "binary large objects" etc), and clearly guile-dbi doesn't have this. Its a fairly small/low-brow package. > have the impression that it's implementation is tied to pg. I didn't even look at guile-pg, because I know that some of the users of my code will insist on mysql. So I had to be agnostic. --linas