=== modified file 'ChangeLog' --- ChangeLog 2013-04-22 11:46:11 +0000 +++ ChangeLog 2013-05-07 10:35:58 +0000 @@ -1,5 +1,8 @@ 5.2.6 + Functionality added or changed: + * Support for File Data Sources. (WL#6583) + Bugs fixed: * With utf8 byte string for mysql server version < 5.5.3, insert fails with error message "Server does not support 4-byte encoded UTF8 === modified file 'driver/connect.c' --- driver/connect.c 2013-04-18 07:22:19 +0000 +++ driver/connect.c 2013-05-03 11:51:17 +0000 @@ -517,6 +517,8 @@ /* We may have to read driver info to find the setup library. */ Driver *pDriver= driver_new(); SQLWCHAR *prompt_instr= NULL; + /* We never know how many new parameters might come out of the prompt */ + SQLWCHAR prompt_outstr[4096]; size_t prompt_inlen; BOOL bPrompt= FALSE; HMODULE hModule= NULL; @@ -715,8 +717,12 @@ sqlwcharncat2(prompt_instr, W_DRIVER_PARAM, &prompt_inlen); sqlwcharncat2(prompt_instr, ds->driver, &prompt_inlen); + /* + In case the client app did not provide the out string we use our + inner buffer prompt_outstr + */ if (!pFunc(hwnd, prompt_instr, fDriverCompletion, - szConnStrOut, cbConnStrOutMax, pcbConnStrOut)) + prompt_outstr, sizeof(prompt_outstr), pcbConnStrOut)) { set_dbc_error(hdbc, "HY000", "User cancelled.", 0); rc= SQL_NO_DATA; @@ -726,15 +732,28 @@ /* refresh our DataSource */ ds_delete(ds); ds= ds_new(); - if (ds_from_kvpair(ds, szConnStrOut, ';')) + if (ds_from_kvpair(ds, prompt_outstr, ';')) { rc= set_dbc_error(dbc, "HY000", "Failed to parse the prompt output string.", 0); goto error; } + + /* + We don't need prompt_outstr after the new DataSource is created. + Copy its contents into szConnStrOut if possible + */ + if (szConnStrOut) + { + *pcbConnStrOut= (SQLSMALLINT)myodbc_min(cbConnStrOutMax, *pcbConnStrOut); + memcpy(szConnStrOut, prompt_outstr, (size_t)*pcbConnStrOut*sizeof(SQLWCHAR)); + /* term needed if possibly truncated */ + szConnStrOut[*pcbConnStrOut - 1] = 0; + } + } - if ((rc= myodbc_do_connect(dbc, ds)) != SQL_SUCCESS) + if (!ds->savefile && (rc= myodbc_do_connect(dbc, ds)) != SQL_SUCCESS) goto error; connected: @@ -797,12 +816,15 @@ } mysql_close(&dbc->mysql); - if (dbc->ds->save_queries) + if (dbc->ds && dbc->ds->save_queries) end_query_log(dbc->query_log); x_free(dbc->database); - assert(dbc->ds); - ds_delete(dbc->ds); + + if(dbc->ds) + { + ds_delete(dbc->ds); + } dbc->ds= NULL; dbc->database= NULL; === modified file 'setupgui/ConfigDSN.c' --- setupgui/ConfigDSN.c 2012-08-09 11:14:17 +0000 +++ setupgui/ConfigDSN.c 2013-05-02 12:47:28 +0000 @@ -57,8 +57,15 @@ { /* truncated, up to caller to see outmax < *outlen */ if (outlen) + { *outlen= ds_to_kvpair_len(ds); - outstr[outmax]= 0; + } + + /* Prevent access violation if outstr is NULL */ + if (outstr) + { + outstr[outmax]= 0; + } } else if (outlen) *outlen= len; === modified file 'setupgui/callbacks.c' --- setupgui/callbacks.c 2013-01-15 23:07:18 +0000 +++ setupgui/callbacks.c 2013-05-01 12:08:16 +0000 @@ -38,6 +38,13 @@ SQLHENV hEnv= SQL_NULL_HENV; SQLWCHAR *rc; + /* + In case of file data source we do not want it to be created + when clicking the Test button + */ + SQLWCHAR *preservedSavefile= params->savefile; + params->savefile= 0; + if (SQL_SUCCEEDED(Connect(&hDbc, &hEnv, params))) rc= sqlwchardup(L"Connection successful", SQL_NTS); else @@ -62,6 +69,9 @@ } } + /* Restore savefile parameter */ + params->savefile= preservedSavefile; + Disconnect(hDbc, hEnv); return rc; } @@ -86,11 +96,19 @@ SQLWCHAR *preservedDatabase= params->database; BOOL preservedNoCatalog= params->no_catalog; + /* + In case of file data source we do not want it to be created + when clicking the Test button + */ + SQLWCHAR *preservedSavefile= params->savefile; + params->savefile= NULL; + params->database= NULL; params->no_catalog= FALSE; nReturn= Connect(&hDbc, &hEnv, params); + params->savefile= preservedSavefile; params->database= preservedDatabase; params->no_catalog= preservedNoCatalog; @@ -159,11 +177,19 @@ SQLWCHAR *preservedDatabase= params->database; BOOL preservedNoCatalog= params->no_catalog; + /* + In case of file data source we do not want it to be created + when clicking the Test button + */ + SQLWCHAR *preservedSavefile= params->savefile; + params->savefile= NULL; + params->database= NULL; params->no_catalog= FALSE; nReturn= Connect(&hDbc, &hEnv, params); + params->savefile= preservedSavefile; params->database= preservedDatabase; params->no_catalog= preservedNoCatalog; === modified file 'test/my_error.c' --- test/my_error.c 2013-03-20 10:13:21 +0000 +++ test/my_error.c 2013-04-22 12:08:12 +0000 @@ -663,13 +663,10 @@ DECLARE_TEST(t_cleartext_password) { SQLHDBC hdbc1; - SQLHSTMT hstmt1; - SQLRETURN rc; SQLCHAR sql_state[6]; SQLINTEGER err_code= 0; SQLCHAR err_msg[SQL_MAX_MESSAGE_LENGTH]= {0}; SQLSMALLINT err_len= 0; - SQLCHAR server_version[MYSQL_NAME_LEN+1]; unsigned int major1= 0, minor1= 0, build1= 0; if (!mysql_min_version(hdbc, "5.5.16", 6) ) === modified file 'test/my_setup.c' --- test/my_setup.c 2013-04-16 13:04:15 +0000 +++ test/my_setup.c 2013-05-06 13:24:21 +0000 @@ -92,8 +92,67 @@ } +/** + Bug #24581: Support File DSN +*/ +DECLARE_TEST(t_bug24581) +{ + /* TODO: remove #ifdef _WIN32 when Linux and MacOS setup is released */ +#ifdef _WIN32 + SQLCHAR grant_query[128]; + SQLCHAR conn_in[512], conn_out[512]; + SQLCHAR conn_fdsn[255]; + SQLCHAR fdsn_path[255]; + SQLSMALLINT conn_out_len; + HDBC hdbc1; + HSTMT hstmt1; + + /* We need a user with minimal privileges and no password */ + sprintf(grant_query, "grant usage on %s.* to 'user24851'@'%s'", + mydb, myserver); + ok_stmt(hstmt, SQLExecDirect(hstmt, grant_query, SQL_NTS)); + + ok_env(henv, SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1)); + + sprintf(fdsn_path, "%s\\filedsn24851.dsn", getenv("TEMP")); + sprintf(conn_in, "DRIVER=%s;SERVER=%s;UID=user24851;DATABASE=%s;"\ + "SAVEFILE=%s", + mydriver, myserver, mydb, fdsn_path); + + /* Create a .dsn file in the TEMP directory, we will remove it later */ + ok_con(hdbc1, SQLDriverConnect(hdbc1, NULL, (SQLCHAR*)conn_in, SQL_NTS, + conn_out, 512, &conn_out_len, SQL_DRIVER_NOPROMPT)); + /* Not necessary, but keep the driver manager happy */ + ok_con(hdbc1, SQLDisconnect(hdbc1)); + + sprintf(conn_fdsn, "FileDSN=%s", fdsn_path); + + /* Connect using the new file DSN */ + ok_con(hdbc1, SQLDriverConnect(hdbc1, NULL, (SQLCHAR*)conn_fdsn, SQL_NTS, + conn_out, 512, &conn_out_len, SQL_DRIVER_NOPROMPT)); + + ok_con(hdbc1, SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1)); + + /* just a simple select to verify the server result */ + ok_sql(hstmt1, "select 24851"); + + ok_stmt(hstmt1, SQLFetch(hstmt1)); + is_num(my_fetch_int(hstmt1, 1), 24851); + + ok_sql(hstmt, "drop user 'user24851'@'localhost'"); + free_basic_handles(NULL, &hdbc1, &hstmt1); + + /* Remove the file DSN */ + is(remove(fdsn_path)==0); +#endif + + return OK; +} + + BEGIN_TESTS ADD_TEST(t_bug66548) + ADD_TEST(t_bug24581) END_TESTS === modified file 'test/odbctap.h' --- test/odbctap.h 2013-04-16 10:33:23 +0000 +++ test/odbctap.h 2013-05-06 11:56:49 +0000 @@ -1249,13 +1249,21 @@ /* We don't care if this succeeds, the connection may have gone away. */ (void)SQLEndTran(SQL_HANDLE_DBC, *hdbc, SQL_COMMIT); - ok_stmt(*hstmt, SQLFreeStmt(*hstmt, SQL_DROP)); - - ok_con(*hdbc, SQLDisconnect(*hdbc)); - - ok_con(*hdbc, SQLFreeConnect(*hdbc)); - - ok_env(*henv, SQLFreeEnv(*henv)); + if(hstmt && *hstmt) + { + ok_stmt(*hstmt, SQLFreeStmt(*hstmt, SQL_DROP)); + } + + if(hdbc && *hdbc) + { + ok_con(*hdbc, SQLDisconnect(*hdbc)); + ok_con(*hdbc, SQLFreeConnect(*hdbc)); + } + + if(henv && *henv) + { + ok_env(*henv, SQLFreeEnv(*henv)); + } return OK; } === modified file 'util/installer.c' --- util/installer.c 2013-04-16 10:33:23 +0000 +++ util/installer.c 2013-04-30 13:07:05 +0000 @@ -167,6 +167,7 @@ {'C','A','N','_','H','A','N','D','L','E','_','E','X','P','_','P','W','D',0}; static SQLWCHAR W_ENABLE_CLEARTEXT_PLUGIN[]= {'E','N','A','B','L','E','_','C','L','E','A', 'R', 'T', 'E', 'X', 'T', '_','P','L','U','G','I','N',0}; +static SQLWCHAR W_SAVEFILE[]= {'S','A','V','E','F','I','L','E',0}; /* DS_PARAM */ /* externally used strings */ @@ -196,7 +197,8 @@ W_MULTI_STATEMENTS, W_COLUMN_SIZE_S32, W_NO_BINARY_RESULT, W_DFLT_BIGINT_BIND_STR, W_CLIENT_INTERACTIVE, W_NO_I_S, W_PREFETCH, W_NO_SSPS, - W_CAN_HANDLE_EXP_PWD, W_ENABLE_CLEARTEXT_PLUGIN}; + W_CAN_HANDLE_EXP_PWD, W_ENABLE_CLEARTEXT_PLUGIN, + W_SAVEFILE}; static const int dsnparamcnt= sizeof(dsnparams) / sizeof(SQLWCHAR *); /* DS_PARAM */ @@ -628,6 +630,7 @@ x_free(ds->sslca); x_free(ds->sslcapath); x_free(ds->sslcipher); + x_free(ds->savefile); x_free(ds->name8); x_free(ds->driver8); @@ -644,6 +647,7 @@ x_free(ds->sslca8); x_free(ds->sslcapath8); x_free(ds->sslcipher8); + x_free(ds->savefile8); x_free(ds); } @@ -739,6 +743,8 @@ *strdest= &ds->sslcapath; else if (!sqlwcharcasecmp(W_SSLCIPHER, param)) *strdest= &ds->sslcipher; + else if (!sqlwcharcasecmp(W_SAVEFILE, param)) + *strdest= &ds->savefile; else if (!sqlwcharcasecmp(W_PORT, param)) *intdest= &ds->port; @@ -1241,6 +1247,7 @@ if (ds_add_strprop(ds->name, W_SSLCA , ds->sslca )) goto error; if (ds_add_strprop(ds->name, W_SSLCAPATH , ds->sslcapath )) goto error; if (ds_add_strprop(ds->name, W_SSLCIPHER , ds->sslcipher )) goto error; + if (ds_add_strprop(ds->name, W_SAVEFILE , ds->savefile )) goto error; if (ds_add_intprop(ds->name, W_SSLVERIFY , ds->sslverify )) goto error; if (ds_add_intprop(ds->name, W_PORT , ds->port )) goto error; === modified file 'util/installer.h' --- util/installer.h 2013-03-20 10:13:21 +0000 +++ util/installer.h 2013-04-23 07:23:10 +0000 @@ -82,6 +82,7 @@ SQLWCHAR *sslca; SQLWCHAR *sslcapath; SQLWCHAR *sslcipher; + SQLWCHAR *savefile; unsigned int port; unsigned int readtimeout; @@ -103,6 +104,7 @@ SQLCHAR *sslca8; SQLCHAR *sslcapath8; SQLCHAR *sslcipher8; + SQLWCHAR *savefile8; /* */ BOOL return_matching_rows;