From c1f20cb4fe807cbaa47085138754dc6dd0e5aae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Thu, 22 Dec 2011 00:31:57 +0000 Subject: [PATCH] [GB.DB] * NEW: Connection.Timeout is a new property that defines the connection timeout in seconds. The value is 20 seconds by default. git-svn-id: svn://localhost/gambas/trunk@4309 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- gb.db.mysql/src/main.c | 12 ++- gb.db.odbc/src/main.c | 175 ++++++++++++++++++++---------------- gb.db.postgresql/src/main.c | 9 +- gb.gtk/src/gprinter.cpp | 2 + main/lib/db/CConnection.c | 13 ++- main/lib/db/gb.db.h | 27 +++--- 6 files changed, 144 insertions(+), 94 deletions(-) diff --git a/gb.db.mysql/src/main.c b/gb.db.mysql/src/main.c index d20d6c5b8..7d0f94ff2 100644 --- a/gb.db.mysql/src/main.c +++ b/gb.db.mysql/src/main.c @@ -599,6 +599,8 @@ static int open_database(DB_DESC *desc, DB_DATABASE *db) char *name; char *host; char *socket; + my_bool reconnect = TRUE; + unsigned int timeout; conn = mysql_init(NULL); @@ -621,8 +623,14 @@ static int open_database(DB_DESC *desc, DB_DATABASE *db) } else socket = NULL; - - if (!mysql_real_connect( conn, host, desc->user, desc->password, + + mysql_options(conn, MYSQL_OPT_RECONNECT, &reconnect); + + timeout = db->timeout; + + mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); + + if (!mysql_real_connect(conn, host, desc->user, desc->password, name, desc->port == NULL ? 0 : atoi(desc->port), socket, CLIENT_MULTI_RESULTS /*client flag */)){ mysql_close(conn); diff --git a/gb.db.odbc/src/main.c b/gb.db.odbc/src/main.c index 929830236..3e5d82d7d 100644 --- a/gb.db.odbc/src/main.c +++ b/gb.db.odbc/src/main.c @@ -524,6 +524,7 @@ fflush(stderr); } + SQLSetConnectAttr(odbc->odbcHandle, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)(intptr_t)db->timeout, 0); /* Connect to Database (Data Source Name) */ retcode =SQLConnect(odbc->odbcHandle, (SQLCHAR *) desc->host, SQL_NTS, (SQLCHAR *) desc->user, SQL_NTS, (SQLCHAR *) desc->password, SQL_NTS); if ((retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO)) @@ -575,7 +576,7 @@ fflush(stderr); static void close_database(DB_DATABASE *db) { - SQLRETURN retcode; + //SQLRETURN retcode; #ifdef ODBC_DEBUG_HEADER fprintf(stderr,"[ODBC][%s][%d]\n",__FILE__,__LINE__); fprintf(stderr,"\tclose_database\n"); @@ -584,37 +585,38 @@ fflush(stderr); ODBC_CONN *conn = (ODBC_CONN *)db->handle; - if (conn->odbcHandle != NULL){ - retcode=SQLDisconnect(conn->odbcHandle); - }else - { - GB.Error("ODBC module internal error"); - } + if (conn->odbcHandle) + SQLDisconnect(conn->odbcHandle); + else + GB.Error("ODBC module internal error"); - - if (conn->odbcHandle != NULL){ - retcode=SQLFreeHandle(SQL_HANDLE_DBC, conn->odbcHandle); - conn->odbcHandle=NULL; - }else + if (conn->odbcHandle) { - GB.Error("ODBC module internal error"); + SQLFreeHandle(SQL_HANDLE_DBC, conn->odbcHandle); + conn->odbcHandle = NULL; } + else + GB.Error("ODBC module internal error"); - if (conn->odbcEnvHandle != NULL){ - retcode=SQLFreeHandle(SQL_HANDLE_ENV, conn->odbcEnvHandle); - conn->odbcEnvHandle=NULL; - }else + if (conn->odbcEnvHandle) { - GB.Error("ODBC module internal error"); + SQLFreeHandle(SQL_HANDLE_ENV, conn->odbcEnvHandle); + conn->odbcEnvHandle = NULL; } + else + GB.Error("ODBC module internal error"); - if (conn->dsn_name != NULL)free(conn->dsn_name); - if (conn->user_name != NULL)free(conn->user_name); - if (conn != NULL){ - SQL_Handle_free(conn); - db->handle=NULL; + if (conn->dsn_name) + free(conn->dsn_name); + + if (conn->user_name) + free(conn->user_name); + + if (conn) + { + SQL_Handle_free(conn); + db->handle = NULL; } - } @@ -1082,14 +1084,12 @@ fflush(stderr); static int query_fill(DB_DATABASE *db, DB_RESULT result, int pos, GB_VARIANT_VALUE * buffer, int next) { - - ODBC_RESULT *res = (ODBC_RESULT *) result; GB_VARIANT value; SQLRETURN retcode2; SQLINTEGER i; ODBC_FIELDS *current; - SQLRETURN retcode; + //SQLRETURN retcode; int nresultcols; SQLINTEGER displaysize; //int V_OD_erg=0; @@ -1100,16 +1100,13 @@ fprintf(stderr,"\tquery_fill result %p,result->odbcStatHandle %p, pos %d\n",res, fflush(stderr); #endif - nresultcols = get_num_columns(res); current = res->fields; for (i = 0; i < nresultcols; i++) { - - if(current->next != NULL)current = (ODBC_FIELDS *) current->next; - - + if(current->next != NULL) + current = (ODBC_FIELDS *) current->next; } @@ -1123,7 +1120,6 @@ fflush(stderr); { retcode2 = SQLFetchScroll(res->odbcStatHandle, SQL_FETCH_NEXT, pos + 1); } - } else { @@ -1176,7 +1172,7 @@ if (displaysize>0) if (type != SQL_LONGVARCHAR && type != SQL_VARBINARY && type != SQL_LONGVARBINARY) { fieldata=malloc(sizeof(char)*(displaysize)); - retcode=SQLGetData(res->odbcStatHandle,i+1,SQL_C_CHAR , fieldata,displaysize,&read); + SQLGetData(res->odbcStatHandle,i+1,SQL_C_CHAR , fieldata,displaysize,&read); } else { @@ -1237,20 +1233,19 @@ return FALSE; static void blob_read(DB_RESULT result, int pos, int field, DB_BLOB *blob) { - - -int i; -//int outlen; -//int precision; -//int scale; -//int displaysize; -//char * pointer; -ODBC_RESULT * res= (ODBC_RESULT *) result; -ODBC_FIELDS * cfield ; -SQLLEN strlen; -SQLRETURN retcode; -i=0; -cfield=res->fields; + int i; + //int outlen; + //int precision; + //int scale; + //int displaysize; + //char * pointer; + ODBC_RESULT * res= (ODBC_RESULT *) result; + ODBC_FIELDS * cfield ; + SQLLEN strlen; + SQLRETURN retcode; + + i = 0; + cfield = res->fields; #ifdef ODBC_DEBUG_HEADER fprintf(stderr,"[ODBC][%s][%d]\n",__FILE__,__LINE__); @@ -1258,49 +1253,71 @@ fprintf(stderr,"\tblob_read DB_RESULT %p, dbresult->stathandle %p, pos %d , fiel fflush(stderr); #endif - while (i < field ){ - - if (cfield->next== NULL){ + while (i < field ) + { + if (cfield->next== NULL) + { GB.Error("ODBC module :Internal error1"); + return; } - cfield=(ODBC_FIELDS *) cfield->next; - if (cfield== NULL){ - GB.Error("ODBC module :Internal error2"); - } - i=i+1; - } - if(i>field) GB.Error("ODBC module : Internal error"); - blob->data=NULL; - if (cfield->outlen > 0) { - blob->data=malloc( sizeof(char)*cfield->outlen); + cfield=(ODBC_FIELDS *) cfield->next; + + if (cfield== NULL) + { + GB.Error("ODBC module :Internal error2"); + return; + } + + i++; + } + + if (i > field) + { + GB.Error("ODBC module : Internal error"); + return; + } + + blob->data=NULL; + if (cfield->outlen > 0) + { + blob->data = malloc( sizeof(char)*cfield->outlen); blob->length = cfield->outlen; DB.Query.Init(); - retcode=SQLGetData(res->odbcStatHandle,field+1,SQL_C_BINARY , blob->data,blob->length, &strlen); - }else + retcode = SQLGetData(res->odbcStatHandle,field+1,SQL_C_BINARY , blob->data,blob->length, &strlen); + + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { - blob->data=NULL; // - blob->length=0; + GB.Error("Unable to retrieve blob data"); + free(blob->data); + blob->length = 0; + blob->data = NULL; + return; } + } + else + { + blob->data = NULL; // + blob->length = 0; + return; + } - char *data; int len; - if (!unquote_blob(blob->data, blob->length, DB.Query.AddLength)) - { - len = DB.Query.Length(); - data = DB.Query.GetNew(); + if (!unquote_blob(blob->data, blob->length, DB.Query.AddLength)) + { + len = DB.Query.Length(); + data = DB.Query.GetNew(); } else blob->constant = TRUE; + free(blob->data);//091107 - blob->data=data; - blob->length=len; - - + blob->data = data; + blob->length = len; } @@ -1415,9 +1432,13 @@ fflush(stderr); retcode=SQLDescribeCol(res->odbcStatHandle, field + 1, colname, sizeof(colname), &colnamelen, &coltype, &precision, &scale, NULL); - - return conv_type(coltype); - + if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) + { + GB.Error("Unable to retrieve field type"); + return GB_T_NULL; + } + else + return conv_type(coltype); } diff --git a/gb.db.postgresql/src/main.c b/gb.db.postgresql/src/main.c index 0a981fb82..b7dbdf61d 100644 --- a/gb.db.postgresql/src/main.c +++ b/gb.db.postgresql/src/main.c @@ -681,13 +681,20 @@ static int open_database(DB_DESC *desc, DB_DATABASE *db) PGresult *res; int status; char *name; + char dbname[512]; if (desc->name) name = desc->name; else name = "template1"; - conn = PQsetdbLogin(desc->host, desc->port, NULL, NULL, name, desc->user, desc->password); + if (snprintf(dbname, sizeof(dbname), "dbname='%s' timeout=%d", get_quote_string(name, strlen(name), '\''), db->timeout) >= sizeof(dbname)) + { + GB.Error("Cannot open database: database name too long"); + return TRUE; + } + + conn = PQsetdbLogin(desc->host, desc->port, NULL, NULL, dbname, desc->user, desc->password); if (!conn) { diff --git a/gb.gtk/src/gprinter.cpp b/gb.gtk/src/gprinter.cpp index cc139c55e..60c6358fa 100644 --- a/gb.gtk/src/gprinter.cpp +++ b/gb.gtk/src/gprinter.cpp @@ -171,7 +171,9 @@ void gPrinter::storeSettings() g_object_unref(G_OBJECT(_settings)); _settings = gtk_print_settings_copy(gtk_print_operation_get_print_settings(_operation)); + #if DEBUG_ME gtk_print_settings_to_file(_settings, "/home/benoit/settings.txt", NULL); + #endif } void gPrinter::defineSettings() diff --git a/main/lib/db/CConnection.c b/main/lib/db/CConnection.c index ef15e95c0..24d9d2afc 100644 --- a/main/lib/db/CConnection.c +++ b/main/lib/db/CConnection.c @@ -149,6 +149,7 @@ BEGIN_METHOD(CCONNECTION_new, GB_STRING url) THIS->db.handle = NULL; THIS->db.ignore_case = FALSE; // Now case is sensitive by default! + THIS->db.timeout = 20; // Connection timeout is 20 seconds by default if (_current == NULL) _current = THIS; @@ -191,7 +192,6 @@ BEGIN_METHOD(CCONNECTION_new, GB_STRING url) } THIS->desc.host = GB.NewZeroString(url); - THIS->desc.name = GB.NewZeroString(name); __BAD_URL: @@ -247,6 +247,16 @@ BEGIN_PROPERTY(CCONNECTION_version) END_PROPERTY +BEGIN_PROPERTY(Connection_Timeout) + + if (READ_PROPERTY) + GB.ReturnInteger(THIS->db.timeout); + else + THIS->db.timeout = VPROP(GB_INTEGER); + +END_PROPERTY + + BEGIN_PROPERTY(CCONNECTION_opened) CHECK_DB(); @@ -722,6 +732,7 @@ GB_DESC CConnectionDesc[] = GB_PROPERTY("Password", "s", CCONNECTION_password), GB_PROPERTY("Name", "s", CCONNECTION_name), GB_PROPERTY("Port", "s", CCONNECTION_port), + GB_PROPERTY("Timeout", "i", Connection_Timeout), GB_PROPERTY_READ("Charset", "s", CCONNECTION_charset), GB_PROPERTY_READ("Version", "i", CCONNECTION_version), GB_PROPERTY_READ("Opened", "b", CCONNECTION_opened), diff --git a/main/lib/db/gb.db.h b/main/lib/db/gb.db.h index 8e8b5c1ac..8da1c3eb3 100644 --- a/main/lib/db/gb.db.h +++ b/main/lib/db/gb.db.h @@ -48,25 +48,26 @@ typedef typedef struct { - void *handle; /* Connection handle */ - int version; /* Version of the database system */ - char *charset; /* Charset used by the database */ - void *data; /* Can be used by the driver for storing its own private data */ + void *handle; /* Connection handle */ + int version; /* Version of the database system */ + char *charset; /* Charset used by the database */ + void *data; /* Can be used by the driver for storing its own private data */ int error; /* Last SQL error code raise by a query */ - unsigned ignore_case : 1; /* If table, field and index names are case sensitive */ + int timeout; /* Connection timeout */ + unsigned ignore_case : 1; /* If table, field and index names are case sensitive */ struct { - unsigned no_table_type : 1; /* Tables do not have types */ - unsigned no_serial : 1; /* Serial fields are not supported */ - unsigned no_blob : 1; /* Blob fields are not supported */ - unsigned no_seek : 1; /* Cannot seek anywhere in a Result */ - unsigned no_nest : 1; /* Cannot nest transactions */ - unsigned no_case : 1; /* If table, field and index names can be case sensitive or not */ + unsigned no_table_type : 1; /* Tables do not have types */ + unsigned no_serial : 1; /* Serial fields are not supported */ + unsigned no_blob : 1; /* Blob fields are not supported */ + unsigned no_seek : 1; /* Cannot seek anywhere in a Result */ + unsigned no_nest : 1; /* Cannot nest transactions */ + unsigned no_case : 1; /* If table, field and index names can be case sensitive or not */ unsigned schema : 1; /* If table names can be prefixed by a schema name and a dot */ } flags; struct { - const char *keyword; /* keyword for limiting the result of a query */ - int pos; /* position of 'limit' keyword */ + const char *keyword; /* keyword for limiting the result of a query */ + int pos; /* position of 'limit' keyword */ } limit; const char *db_name_char; /* These characters are allowed in a database name */