mirror of
https://github.com/mariadb-corporation/mariadb-connector-cpp.git
synced 2025-07-22 18:27:20 +00:00
3464 lines
94 KiB
C++
3464 lines
94 KiB
C++
/*
|
|
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
* 2020, 2025 MariaDB Corporation plc
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, version 2.0, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is also distributed with certain software (including
|
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
|
* as designated in a particular file or component or in included license
|
|
* documentation. The authors of MySQL hereby grant you an
|
|
* additional permission to link the program and your derivative works
|
|
* with the separately licensed software that they have included with
|
|
* MySQL.
|
|
*
|
|
* Without limiting anything contained in the foregoing, this file,
|
|
* which is part of MySQL Connector/C++, is also subject to the
|
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License, version 2.0, for more details.
|
|
*
|
|
* 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.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
|
|
#include "Warning.hpp"
|
|
|
|
#include "connectiontest.h"
|
|
#include <stdlib.h>
|
|
#include <fstream>
|
|
#include "Connection.hpp"
|
|
|
|
#include "Exception.hpp"
|
|
|
|
#include <memory>
|
|
#include <list>
|
|
#include <thread>
|
|
#include <functional>
|
|
|
|
namespace testsuite
|
|
{
|
|
namespace classes
|
|
{
|
|
|
|
void connection::getClientInfo()
|
|
{
|
|
logMsg("connection::getClientInfo() - MySQL_Connection::getClientInfo()");
|
|
SKIP("Not supported yet");
|
|
try
|
|
{
|
|
std::string ret;
|
|
|
|
//ret= con->getClientInfo();
|
|
if (ret != "cppconn")
|
|
FAIL(("Expecting 'cppconn' got '" + ret + "'.").c_str());
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::getClientOption()
|
|
{
|
|
logMsg("connection::getClientOption() - MySQL_Connection::get|setClientOption()");
|
|
SKIP("Not supported yet");
|
|
try
|
|
{
|
|
const std::string option("metadataUseInfoSchema");
|
|
|
|
{
|
|
bool input_value=true;
|
|
bool output_value=false;
|
|
void * input;
|
|
void * output;
|
|
|
|
input=(static_cast<bool *> (&input_value));
|
|
output=(static_cast<bool *> (&output_value));
|
|
|
|
con->setClientOption("metadataUseInfoSchema", input);
|
|
con->getClientOption("metadataUseInfoSchema", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
con->setClientOption("metadataUseInfoSchema", input);
|
|
con->getClientOption("metadataUseInfoSchema", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
input_value=false;
|
|
output_value=true;
|
|
con->setClientOption("metadataUseInfoSchema", input);
|
|
con->getClientOption("metadataUseInfoSchema", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
}
|
|
|
|
{
|
|
int input_value= sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
|
int output_value= sql::ResultSet::TYPE_FORWARD_ONLY;
|
|
void * input;
|
|
void * output;
|
|
|
|
input=(static_cast<int *> (&input_value));
|
|
output=(static_cast<int *> (&output_value));
|
|
|
|
con->setClientOption("defaultStatementResultType", input);
|
|
con->getClientOption("defaultStatementResultType", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
input_value= sql::ResultSet::TYPE_FORWARD_ONLY;
|
|
output_value= sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
|
con->setClientOption("defaultStatementResultType", input);
|
|
con->getClientOption("defaultStatementResultType", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
try
|
|
{
|
|
input_value=sql::ResultSet::TYPE_SCROLL_SENSITIVE;
|
|
con->setClientOption("defaultStatementResultType", input);
|
|
FAIL("API Change or bug, please check");
|
|
}
|
|
catch (sql::InvalidArgumentException &)
|
|
{
|
|
/* expected */
|
|
}
|
|
|
|
try
|
|
{
|
|
input_value=sql::ResultSet::TYPE_SCROLL_SENSITIVE + sql::ResultSet::TYPE_SCROLL_INSENSITIVE + sql::ResultSet::TYPE_FORWARD_ONLY;
|
|
con->setClientOption("defaultStatementResultType", input);
|
|
FAIL("API Change or bug, please check");
|
|
}
|
|
catch (sql::InvalidArgumentException &)
|
|
{
|
|
/* expected */
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
bool input_value=true;
|
|
bool output_value=false;
|
|
void * input;
|
|
void * output;
|
|
|
|
input=(static_cast<bool *> (&input_value));
|
|
output=(static_cast<bool *> (&output_value));
|
|
|
|
con->setClientOption("defaultPreparedStatementResultType", input);
|
|
con->getClientOption("defaultPreparedStatementResultType", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
input_value=false;
|
|
output_value=true;
|
|
con->setClientOption("defaultPreparedStatementResultType", input);
|
|
con->getClientOption("defaultPreparedStatementResultType", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
|
|
}
|
|
catch (sql::MethodNotImplementedException &)
|
|
{
|
|
/* compiled without -DWE_SUPPORT_USE_RESULT_WITH_PS */
|
|
}
|
|
|
|
try
|
|
{
|
|
sql::SQLString input_value("latin1");
|
|
sql::SQLString output_value;
|
|
|
|
con->setClientOption("characterSetResults", input_value);
|
|
|
|
output_value=con->getClientOption("characterSetResults");
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
int serverVersion=getServerVersion(con);
|
|
if ( serverVersion >= 507003)
|
|
{
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap opts;
|
|
int input_value=111;
|
|
int output_value=2367;
|
|
void *output;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["OPT_READ_TIMEOUT"]= "111";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(opts));
|
|
|
|
output= static_cast<void *> (&output_value);
|
|
con->getClientOption("OPT_READ_TIMEOUT", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap opts;
|
|
bool input_value=true;
|
|
bool output_value=false;
|
|
void *output;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["OPT_RECONNECT"]= input_value ? "1" : "0";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(opts));
|
|
|
|
output= static_cast<void *> (&output_value);
|
|
con->getClientOption("OPT_RECONNECT", output);
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap opts;
|
|
sql::SQLString input_value("../lib/plugin/");
|
|
const char *output_value="../lib/plugin/";
|
|
void *output;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["pluginDir"]=input_value;
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(opts));
|
|
|
|
output= static_cast<void*> (&output_value);
|
|
con->getClientOption("pluginDir", output);
|
|
|
|
ASSERT_EQUALS(input_value, output_value);
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
//sql::SQLString tmp=con->getClientOption("characterSetDirectory");
|
|
//tmp=con->getClientOption("readDefaultFile");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::getSessionVariable()
|
|
{
|
|
logMsg("connection::getSessionVariable() - MySQL_Connection::get|setSessionVariable()");
|
|
#ifdef GETSET_SESSIONVARIABLE_IMPLEMENTED
|
|
|
|
try
|
|
{
|
|
std::string value("");
|
|
std::unique_ptr<Connection> my_con(driver->connect(url, user, passwd));
|
|
value=my_con->getSessionVariable("sql_mode");
|
|
|
|
my_con->setSessionVariable("sql_mode", "ANSI");
|
|
// The server will translate ANSI into something that is version dependent -
|
|
// ASSERT_EQUALS(my_con->getSessionVariable("sql_mode"), "");
|
|
|
|
my_con->setSessionVariable("sql_mode", value);
|
|
ASSERT_EQUALS(value, my_con->getSessionVariable("sql_mode"));
|
|
|
|
value=my_con->getSessionVariable("sql_warnings");
|
|
|
|
std::string on("ON");
|
|
std::string off("OFF");
|
|
try
|
|
{
|
|
my_con->setSessionVariable("sql_warnings", "0");
|
|
on="1";
|
|
off="0";
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
my_con->setSessionVariable("sql_warnings", on);
|
|
ASSERT_EQUALS(on, my_con->getSessionVariable("sql_warnings"));
|
|
my_con->setSessionVariable("sql_warnings", off);
|
|
ASSERT_EQUALS(off, my_con->getSessionVariable("sql_warnings"));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
my_con->setSessionVariable("sql_warnings", value);
|
|
ASSERT_EQUALS(value, my_con->getSessionVariable("sql_warnings"));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
#else
|
|
SKIP("Private interface is not exposed, get/setSessionVariable not supported")
|
|
#endif // GETSET_SESSIONVARIABLE_IMPLEMENTED
|
|
}
|
|
|
|
void connection::getNoWarningsOnNewLine()
|
|
{
|
|
logMsg("connection::getNoWarningsOnNewLine() - MySQL_Connection::getWarnings()");
|
|
try
|
|
{
|
|
const sql::SQLWarning* warning;
|
|
|
|
warning=con->getWarnings();
|
|
if (warning != NULL)
|
|
FAIL("There should be no warnings on the default connection");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::invalidCredentials()
|
|
{
|
|
if (useTls) {
|
|
logMsg("skip because TLS is needed");
|
|
return void();
|
|
}
|
|
|
|
logMsg("connection::invalidCredentials() - MySQL_Connection connect");
|
|
std::string myurl("tcp://");
|
|
std::string myuser("");
|
|
std::string mypasswd("");
|
|
|
|
try
|
|
{
|
|
try
|
|
{
|
|
con.reset(driver->connect(myurl, user, passwd));
|
|
logMsg("... using invalid URL should have failed, but we can't be sure that is it an issue, because we do not know for sure what defaults a test system is using,");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
logMsg("... using wrong URL caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
}
|
|
|
|
if (!url.empty())
|
|
{
|
|
try
|
|
{
|
|
con.reset(driver->connect("", user, passwd));
|
|
logMsg("... using empty URL should have failed, but we can't be sure that is it an issue, because we do not know for sure what defaults a test system is using,");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... using empty URL caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
try
|
|
{
|
|
con.reset(driver->connect("", user, passwd));
|
|
FAIL("Should have caused exception");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
if (user.empty())
|
|
{
|
|
myuser.append("H17ba76inosuchuser");
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, myuser, passwd));
|
|
FAIL("... using invalid user should cause failure");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... using wrong URL caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, myuser, passwd));
|
|
FAIL("Should have caused exception");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Its a guess, but usually such a user won't exist... */
|
|
myuser.append(user);
|
|
myuser.append(user);
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, myuser, myuser));
|
|
FAIL("... using invalid user should have failed");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... using wrong user caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, myuser, myuser));
|
|
FAIL("Should have caused exception");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
if (passwd.empty())
|
|
{
|
|
mypasswd.append("27jahjk327ahime27879xas");
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, user, mypasswd));
|
|
FAIL("... using invalid password should cause failure");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... using wrong password caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, user, mypasswd));
|
|
FAIL("Should have caused exception");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mypasswd.append(passwd);
|
|
mypasswd.append(passwd);
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, user, mypasswd));
|
|
if (getServerVersion(con) > 1100000)
|
|
{
|
|
logMsg("... with server version > 11.0 and root/Administrator account running tests, this may happen");
|
|
}
|
|
else
|
|
{
|
|
FAIL("... using invalid password should have failed");
|
|
}
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... using wrong password caused expected failure");
|
|
con.reset(driver->connect(url, user, passwd));
|
|
try
|
|
{
|
|
con.reset(driver->connect(url, user, mypasswd));
|
|
FAIL("Should have caused exception");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::getNoWarningsAfterClear()
|
|
{
|
|
logMsg("connection::getNoWarningsAfterClear() - MySQL_Connection::getWarnings()");
|
|
try
|
|
{
|
|
const sql::SQLWarning* warning;
|
|
|
|
/* TODO: pointless test as there is no warning before running clearWarnings() */
|
|
con->clearWarnings();
|
|
warning=con->getWarnings();
|
|
if (warning != NULL)
|
|
FAIL("There should be no warnings on the default connection");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::checkClosed()
|
|
{
|
|
logMsg("connection::checkClosed - MySQL_Connection::close, isClosed() and internal check_closed()");
|
|
try
|
|
{
|
|
if (con->isClosed())
|
|
FAIL("Connection should not be reported as closed");
|
|
|
|
con->close();
|
|
|
|
if (!con->isClosed())
|
|
FAIL("Connection should be closed");
|
|
|
|
try
|
|
{
|
|
con->rollback();
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
std::string reason(exceptionIsOK(e, "HY000", 0));
|
|
if (!reason.empty())
|
|
fail(reason.c_str(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::connectUsingMapWrongTypes()
|
|
{
|
|
logMsg("connection::connectUsingMapWrongTypes - using map to pass connection parameters but parameter of wrong type");
|
|
SKIP("Not rellevant or needs adaptation");
|
|
#ifdef MISSING_STUFF_SUPPORT_ADDED
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap connection_properties;
|
|
bool boolval=true;
|
|
std::string strval("");
|
|
|
|
connection_properties["useTls"]= useTls? "true" : "false";
|
|
try
|
|
{
|
|
connection_properties["hostName"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception I");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("hostName");
|
|
connection_properties["hostName"]=url;
|
|
|
|
try
|
|
{
|
|
connection_properties["userName"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception II");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("userName");
|
|
connection_properties["userName"]=user;
|
|
|
|
try
|
|
{
|
|
connection_properties["password"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception III");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("password");
|
|
connection_properties["password"]=passwd;
|
|
|
|
try
|
|
{
|
|
connection_properties["port"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception IV");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("port");
|
|
|
|
try
|
|
{
|
|
connection_properties["socket"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception V");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("socket");
|
|
|
|
try
|
|
{
|
|
connection_properties["pipe"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception VI");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("pipe");
|
|
|
|
try
|
|
{
|
|
connection_properties["schema"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception VII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("schema");
|
|
|
|
try
|
|
{
|
|
connection_properties["characterSetResults"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception VIII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("characterSetResults");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslKey"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception IX");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslKey");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCert"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception X");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCert");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCA"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XI");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCA");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCAPath"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCAPath");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCipher"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XIII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCipher");
|
|
|
|
/*
|
|
TODO -- will be moved into driver class.
|
|
try
|
|
{
|
|
connection_properties["clientlib"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XIV");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
expected
|
|
}
|
|
connection_properties.erase("clientlib");
|
|
*/
|
|
|
|
try
|
|
{
|
|
connection_properties["defaultStatementResultType"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XV");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("defaultStatementResultType");
|
|
|
|
try
|
|
{
|
|
connection_properties["metadataUseInfoSchema"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XVI");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("metadataUseInfoSchema");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_COMPRESS"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XVII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_COMPRESS");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_FOUND_ROWS"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XVIII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_FOUND_ROWS");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_IGNORE_SIGPIPE"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XIX");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_IGNORE_SIGPIPE");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_IGNORE_SPACE"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XX");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_IGNORE_SPACE");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_INTERACTIVE"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXI");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_INTERACTIVE");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_LOCAL_FILES"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_LOCAL_FILES");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_MULTI_STATEMENTS"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXIII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_MULTI_STATEMENTS");
|
|
|
|
try
|
|
{
|
|
connection_properties["CLIENT_NO_SCHEMA"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXIV");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("CLIENT_NO_SCHEMA");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_CONNECT_TIMEOUT"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXV");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_CONNECT_TIMEOUT");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_READ_TIMEOUT"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXVI");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_READ_TIMEOUT");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_WRITE_TIMEOUT"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXVII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_WRITE_TIMEOUT");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_RECONNECT"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXVIII");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_CHARSET_NAME"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXIX");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_CHARSET_NAME");
|
|
|
|
try
|
|
{
|
|
connection_properties["OPT_REPORT_DATA_TRUNCATION"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXX");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("OPT_REPORT_DATA_TRUNCATION");
|
|
|
|
#if MYCPPCONN_STATIC_MYSQL_VERSION_ID < 80000
|
|
try
|
|
{
|
|
connection_properties["sslVerify"]=(strval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXXI - sslVerify");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslVerify");
|
|
#endif
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCRL"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXXII - sslCRL");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCRL");
|
|
|
|
try
|
|
{
|
|
connection_properties["sslCRLPath"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXXIII - sslCRLPath");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("sslCRLPath");
|
|
|
|
try
|
|
{
|
|
connection_properties["rsaKey"]=(boolval);
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("No exception XXXIII - rsaKey");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
/* expected */
|
|
}
|
|
connection_properties.erase("rsaKey");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void connection::connectUsingMap()
|
|
{
|
|
logMsg("connection::connectUsingMap - using map to pass connection parameters");
|
|
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]=urlWithoutSchema;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
connection_properties["useTls"]= useTls? "true" : "false";
|
|
|
|
bool bval= !TestsRunner::getStartOptions()->getBool("dont-use-is");
|
|
connection_properties["metadataUseInfoSchema"]=(bval ? "true" : "false");
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
|
|
/*
|
|
The property map now contains the minimum required entries and it works.
|
|
Lets play with so-to-say optional entries.
|
|
*/
|
|
|
|
/* 1) Port */
|
|
connection_properties.erase("port");
|
|
{
|
|
sql::SQLString port("-1");
|
|
if (url.compare(0, sizeof ("tcp://") - 1, "tcp://") == 0 || url.compare(0, sizeof("jdbc:mariadb:") - 1, "jdbc:mariadb://") == 0)
|
|
{
|
|
size_t port_pos;
|
|
port_pos=url.find_last_of(":", std::string::npos);
|
|
if (port_pos != std::string::npos)
|
|
port= url.substr(port_pos + 1, std::string::npos).c_str();
|
|
|
|
if (port.compare("-1") == 0)
|
|
{
|
|
/* The user is using TCP/IP and default port 3306 */
|
|
connection_properties["port"]=(port);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("Connect works with invalid port of -1");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
std::string reason(exceptionIsOK(e, "HY000", 2003));
|
|
logErr(reason);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The user is using TCP/IP and has specified the port.
|
|
A port setting shall NOT overrule the setting from the URL */
|
|
port= "-1";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("URL shall overrule port setting");
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* We must be using a socket connection - all port settings shall be ignored */
|
|
connection_properties["port"]=(port);
|
|
/* Must not throw an exception */
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Port setting should be ignored, using Unix socket!");
|
|
}
|
|
}
|
|
}
|
|
connection_properties.erase("port");
|
|
|
|
/* 2) Socket */
|
|
connection_properties.erase("socket");
|
|
{
|
|
std::string socket("");
|
|
#ifndef CPPWIN_WIN32
|
|
|
|
if (url.compare(0, sizeof ("unix://") - 1, "unix://") == 0)
|
|
{
|
|
// Unix socket connection
|
|
socket="I hope this is invalid";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Socket setting should be ignored, socket is part of the URL");
|
|
}
|
|
|
|
}
|
|
else
|
|
#endif
|
|
if (url.compare(0, sizeof ("tcp://") - 1, "tcp://") == 0)
|
|
{
|
|
// TCP/IP connection, socket shall be ignored
|
|
socket="I hope this is invalid";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Socket setting should be ignored because its a TCP/IP connection");
|
|
}
|
|
}
|
|
}
|
|
connection_properties.erase("socket");
|
|
|
|
/* 2) Schema */
|
|
connection_properties.erase("schema");
|
|
{
|
|
std::string schema("");
|
|
std::string myschema("mysql");
|
|
std::string retschema("");
|
|
|
|
if (url.compare(0, sizeof ("tcp://") - 1, "tcp://") == 0)
|
|
{
|
|
// TCP/IP connection - schema cannot be set when using unix socket syntax
|
|
size_t schema_pos;
|
|
std::string host(url.substr(sizeof ("tcp://") - 1, std::string::npos));
|
|
schema_pos=host.find("/");
|
|
if (schema_pos != std::string::npos)
|
|
{
|
|
schema_pos++;
|
|
schema=host.substr(schema_pos, host.size() - schema_pos);
|
|
}
|
|
}
|
|
|
|
if (schema.empty())
|
|
{
|
|
logMsg("... schema not set through the URL");
|
|
|
|
connection_properties["schema"]= schema;
|
|
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
schema= con->getSchema();
|
|
if (!schema.empty())
|
|
FAIL("Empty schama specified but certain schema selected upon connect");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Connect should have worked although schema property set to empty string");
|
|
}
|
|
|
|
|
|
logMsg("... trying to connect to mysql schema, may or may not work");
|
|
|
|
connection_properties.erase("schema");
|
|
connection_properties["schema"]= (myschema);
|
|
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
Connection mycon(driver->connect(connection_properties));
|
|
retschema=mycon->getSchema();
|
|
if (retschema != myschema)
|
|
{
|
|
logErr(retschema);
|
|
logErr(myschema);
|
|
logErr(mycon->getCatalog());
|
|
logErr(mycon->getSchema());
|
|
FAIL("Connected to schema mysql but getSchema() reports different schema");
|
|
}
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
logMsg("... cannot connect to mysql schema but that is OK, might be insufficient grants");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* schema is set in the TCP/IP url */
|
|
logMsg("... schema is set in the URL and property shall be ignored");
|
|
|
|
/* no property set */
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
retschema=con->getSchema();
|
|
if (retschema != schema)
|
|
{
|
|
logErr(retschema);
|
|
logErr(schema);
|
|
FAIL("Connected to a certain schema but getSchema() reports different schema");
|
|
}
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Connect should not fail");
|
|
}
|
|
|
|
/* property set */
|
|
connection_properties["schema"]=(myschema);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
retschema=con->getSchema();
|
|
if (retschema != schema)
|
|
{
|
|
logErr(retschema);
|
|
logErr(schema);
|
|
FAIL("Connected to a certain schema but getSchema() reports different schema");
|
|
}
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
FAIL("Connect should not fail");
|
|
}
|
|
}
|
|
}
|
|
connection_properties.erase("schema");
|
|
|
|
/* 3) ssl* */
|
|
connection_properties.erase("sslKey");
|
|
connection_properties.erase("sslCert");
|
|
connection_properties.erase("sslCA");
|
|
connection_properties.erase("sslCAPath");
|
|
connection_properties.erase("sslCipher");
|
|
{
|
|
logMsg("... setting bogus SSL properties");
|
|
std::string sql("ramdom bogus value");
|
|
connection_properties["sslKey"]=(sql);
|
|
connection_properties["sslCert"]=(sql);
|
|
connection_properties["sslCA"]=(sql);
|
|
connection_properties["sslCAPath"]=(sql);
|
|
connection_properties["sslCipher"]=(sql);
|
|
/*
|
|
mysql_ssl_set is silly:
|
|
This function always returns 0.
|
|
If SSL setup is incorrect, mysql_real_connect()
|
|
returns an error when you attempt to connect.
|
|
*/
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
}
|
|
connection_properties.erase("sslKey");
|
|
connection_properties.erase("sslCert");
|
|
connection_properties.erase("sslCA");
|
|
connection_properties.erase("sslCAPath");
|
|
connection_properties.erase("sslCipher");
|
|
|
|
/* All the CLIENT* are pointless. There is no way (yet) to verify the settings */
|
|
/* 4) CLIENT_COMPRESS */
|
|
connection_properties.erase("CLIENT_COMPRESS");
|
|
{
|
|
logMsg("... testing CLIENT_COMPRESS");
|
|
connection_properties["CLIENT_COMPRESS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_COMPRESS"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_COMPRESS");
|
|
|
|
/* 5) CLIENT_FOUND_ROWS */
|
|
connection_properties.erase("CLIENT_FOUND_ROWS");
|
|
{
|
|
logMsg("... testing CLIENT_FOUND_ROWS");
|
|
connection_properties["CLIENT_FOUND_ROWS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_FOUND_ROWS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_FOUND_ROWS");
|
|
connection_properties["CLIENT_FOUND_ROWS"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_FOUND_ROWS");
|
|
|
|
/* 6) CLIENT_IGNORE_SIGPIPE */
|
|
connection_properties.erase("CLIENT_IGNORE_SIGPIPE");
|
|
{
|
|
logMsg("... testing CLIENT_IGNORE_SIGPIPE");
|
|
connection_properties["CLIENT_IGNORE_SIGPIPE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_IGNORE_SIGPIPE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_IGNORE_SIGPIPE"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_IGNORE_SIGPIPE");
|
|
|
|
/* 7) CLIENT_IGNORE_SPACE */
|
|
connection_properties.erase("CLIENT_IGNORE_SPACE");
|
|
{
|
|
logMsg("... testing CLIENT_IGNORE_SPACE");
|
|
connection_properties["CLIENT_IGNORE_SPACE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_IGNORE_SPACE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_IGNORE_SPACE");
|
|
connection_properties["CLIENT_IGNORE_SPACE"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_IGNORE_SPACE");
|
|
|
|
/* 8) CLIENT_INTERACTIVE */
|
|
connection_properties.erase("CLIENT_INTERACTIVE");
|
|
{
|
|
logMsg("... testing CLIENT_INTERACTIVE");
|
|
connection_properties["CLIENT_INTERACTIVE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_INTERACTIVE"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_INTERACTIVE");
|
|
connection_properties["CLIENT_INTERACTIVE"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_INTERACTIVE");
|
|
|
|
/* 9) CLIENT_LOCAL_FILES */
|
|
/* TODO - add proper test */
|
|
connection_properties.erase("CLIENT_LOCAL_FILES");
|
|
{
|
|
logMsg("... testing CLIENT_LOCAL_FILES");
|
|
connection_properties["CLIENT_LOCAL_FILES"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_LOCAL_FILES"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_LOCAL_FILES");
|
|
connection_properties["CLIENT_LOCAL_FILES"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_LOCAL_FILES");
|
|
|
|
/* 10) CLIENT_MULTI_RESULTS */
|
|
/* TODO - add proper test */
|
|
connection_properties.erase("CLIENT_MULTI_RESULTS");
|
|
{
|
|
logMsg("... testing CLIENT_MULTI_RESULTS");
|
|
connection_properties["CLIENT_MULTI_RESULTS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_MULTI_RESULTS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_MULTI_RESULTS");
|
|
connection_properties["CLIENT_MULTI_RESULTS"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_MULTI_RESULTS");
|
|
|
|
/* 11) CLIENT_MULTI_STATEMENTS */
|
|
/* TODO: add proper test */
|
|
connection_properties.erase("CLIENT_MULTI_STATEMENTS");
|
|
{
|
|
logMsg("... testing CLIENT_MULTI_STATEMENTS");
|
|
connection_properties["CLIENT_MULTI_STATEMENTS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_MULTI_STATEMENTS"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_MULTI_STATEMENTS");
|
|
connection_properties["CLIENT_MULTI_STATEMENTS"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_MULTI_STATEMENTS");
|
|
|
|
/* 12) CLIENT_NO_SCHEMA */
|
|
connection_properties.erase("CLIENT_NO_SCHEMA");
|
|
{
|
|
logMsg("... testing CLIENT_NO_SCHEMA");
|
|
connection_properties["CLIENT_NO_SCHEMA"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties["CLIENT_NO_SCHEMA"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
connection_properties.erase("CLIENT_NO_SCHEMA");
|
|
connection_properties["CLIENT_NO_SCHEMA"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
connection_properties.erase("CLIENT_NO_SCHEMA");
|
|
|
|
/* 13) MYSQL_OPT_CONNECT_TIMEOUT */
|
|
connection_properties.erase("OPT_CONNECT_TIMEOUT");
|
|
{
|
|
logMsg("... testing OPT_CONNECT_TIMEOUT");
|
|
/*
|
|
C-API does not care about the actual value, its passed down to the OS,
|
|
The OS may or may not detect bogus values such as negative values.
|
|
*/
|
|
connection_properties["OPT_CONNECT_TIMEOUT"]="1";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_CONNECT_TIMEOUT");
|
|
|
|
/* 14) MYSQL_OPT_READ_TIMEOUT */
|
|
connection_properties.erase("OPT_READ_TIMEOUT");
|
|
{
|
|
logMsg("... testing OPT_READ_TIMEOUT");
|
|
/*
|
|
C-API does not care about the actual value, its passed down to the OS,
|
|
The OS may or may not detect bogus values such as negative values.
|
|
*/
|
|
connection_properties["OPT_READ_TIMEOUT"]="1";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_READ_TIMEOUT");
|
|
|
|
/* 15) MYSQL_OPT_WRITE_TIMEOUT */
|
|
connection_properties.erase("OPT_WRITE_TIMEOUT");
|
|
{
|
|
logMsg("... testing OPT_WRITE_TIMEOUT");
|
|
/* C-API does not care about the actual value */
|
|
connection_properties["OPT_WRITE_TIMEOUT"]="1";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_WRITE_TIMEOUT");
|
|
|
|
/* 16) MYSQL_OPT_RECONNECT */
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
{
|
|
logMsg("... testing OPT_RECONNECT");
|
|
/* C-API does not care about the actual value */
|
|
connection_properties["OPT_RECONNECT"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
|
|
/* 17) MYSQL_OPT_SET_CHARSET_NAME */
|
|
connection_properties.erase("OPT_SET_CHARSET_NAME");
|
|
{
|
|
logMsg("... testing OPT_SET_CHARSET_NAME");
|
|
std::string charset("utf8");
|
|
/* C-API does not care about the actual value */
|
|
connection_properties["OPT_SET_CHARSET_NAME"]=(charset);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_SET_CHARSET_NAME");
|
|
|
|
/* 18) MYSQL_REPORT_DATA_TRUNCATION */
|
|
connection_properties.erase("REPORT_DATA_TRUNCATION");
|
|
{
|
|
logMsg("... testing REPORT_DATA_TRUNCATION");
|
|
std::string charset("1");
|
|
/* C-API does not care about the actual value */
|
|
connection_properties["REPORT_DATA_TRUNCATION"]=(charset);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("REPORT_DATA_TRUNCATION");
|
|
|
|
|
|
/* 19) metadataUseInfoSchema */
|
|
connection_properties.erase("metadataUseInfoSchema");
|
|
{
|
|
logMsg("... testing metadataUseInfoSchema");
|
|
connection_properties["metadataUseInfoSchema"]= "true";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
connection_properties.erase("metadataUseInfoSchema");
|
|
connection_properties["metadataUseInfoSchema"]="false";
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("metadataUseInfoSchema");
|
|
|
|
/* 20) defaultStatementResultType */
|
|
connection_properties.erase("defaultStatementResultType");
|
|
{
|
|
logMsg("... testing defaultStatementResultType");
|
|
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_FORWARD_ONLY);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
connection_properties.erase("defaultStatementResultType");
|
|
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
connection_properties.erase("defaultStatementResultType");
|
|
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_SCROLL_SENSITIVE);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
try
|
|
{
|
|
con.reset(driver->connect(connection_properties));
|
|
//FAIL("Bug or API change - TYPE_SCROLL_SENSITIVE is unsupported");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logMsg("... expected exception because TYPE_SCROLL_SENSITIVE is unsupported!");
|
|
logMsg(e.what());
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
connection_properties.erase("defaultStatementResultType");
|
|
|
|
#ifdef CPPWIN_WIN32
|
|
/* 21) OPT_NAMED_PIPE - handled but ignored! */
|
|
connection_properties.erase("OPT_NAMED_PIPE");
|
|
{
|
|
logMsg("... testing OPT_NAMED_PIPE");
|
|
std::string pipe("IGNORED");
|
|
connection_properties["OPT_NAMED_PIPE"]=(pipe);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_NAMED_PIPE");
|
|
#endif
|
|
|
|
/* 22) OPT_CHARSET_NAME = MYSQL_SET_CHARSET_NAME */
|
|
connection_properties.erase("OPT_CHARSET_NAME");
|
|
{
|
|
logMsg("... testing OPT_CHARSET_NAME");
|
|
std::string charset("utf8");
|
|
connection_properties["OPT_CHARSET_NAME"]=(charset);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_CHARSET_NAME");
|
|
|
|
|
|
/* 23) OPT_REPORT_DATA_TRUNCATION */
|
|
connection_properties.erase("OPT_REPORT_DATA_TRUNCATION");
|
|
{
|
|
logMsg("... testing OPT_REPORT_DATA_TRUNCATION");
|
|
connection_properties["OPT_REPORT_DATA_TRUNCATION"]= "true";// (true);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
connection_properties.erase("OPT_REPORT_DATA_TRUNCATION");
|
|
connection_properties["OPT_REPORT_DATA_TRUNCATION"]= "false";//(false);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
connection_properties.erase("OPT_REPORT_DATA_TRUNCATION");
|
|
|
|
/* 24) defaultPreparedStatementResultType */
|
|
connection_properties.erase("defaultPreparedStatementResultType");
|
|
{
|
|
logMsg("... testing defaultPreparedStatementResultType");
|
|
connection_properties["defaultPreparedStatementResultType"]= std::to_string(sql::ResultSet::TYPE_FORWARD_ONLY);
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
/* may not be compiled in - ignore */
|
|
}
|
|
}
|
|
connection_properties.erase("defaultPreparedStatementResultType");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
|
|
void connection::connectOptReconnect()
|
|
{
|
|
logMsg("connection::connectOptReconnect - OPT_RECONNECT");
|
|
std::stringstream msg;
|
|
if (isMaxScale()) {
|
|
printf("# <<<< canceled for maxscale \n# ");
|
|
return void();
|
|
}
|
|
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]=url;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
connection_properties["useTls"]= useTls? "true" : "false";
|
|
|
|
bool bval= !TestsRunner::getStartOptions()->getBool("dont-use-is");
|
|
connection_properties["metadataUseInfoSchema"]=(bval? "true" : "false");
|
|
|
|
logMsg("... OPT_RECONNECT disabled");
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
|
|
con->close();
|
|
ASSERT(con->isClosed());
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
FAIL("Can create statement although connection has been closed");
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
/* expected */
|
|
}
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
|
|
ASSERT_EQUALS(false, con->isClosed());
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
logMsg("... OPT_RECONNECT enabled");
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "true";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
|
|
con->close();
|
|
ASSERT(con->isClosed());
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
FAIL("Can create statement although connection has been closed");
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
/* expected */
|
|
}
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "true";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
|
|
ASSERT_EQUALS(false, con->isClosed());
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
logMsg("... OPT_RECONNECT disabled and KILL");
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT CONNECTION_ID() as _pid"));
|
|
ASSERT(res->next());
|
|
msg.str("");
|
|
msg << "KILL " << res->getInt("_pid");
|
|
|
|
try
|
|
{
|
|
Connection my_con(getConnection());
|
|
my_con->setSchema(db);
|
|
Statement my_stmt(my_con->createStatement());
|
|
my_stmt->execute(msg.str());
|
|
logMsg("... we seem to be lucky, we have killed a connection");
|
|
logMsg(msg.str());
|
|
try
|
|
{
|
|
msg.str("");
|
|
msg << "USE " << db;
|
|
stmt->execute(msg.str());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
FAIL("Statement object is still usable");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
// Any error message is fine, connection should have been killed
|
|
logMsg(e.what());
|
|
}
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
// KILL has failed - that is OK, we may not have permissions
|
|
}
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT CONNECTION_ID() as _pid"));
|
|
ASSERT(res->next());
|
|
msg.str("");
|
|
msg << "KILL " << res->getInt("_pid");
|
|
|
|
try
|
|
{
|
|
Connection my_con(getConnection());
|
|
my_con->setSchema(db);
|
|
Statement my_stmt(my_con->createStatement());
|
|
my_stmt->execute(msg.str());
|
|
logMsg("... we seem to be lucky, we have killed a connection");
|
|
logMsg(msg.str());
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
logMsg("... we got a new statement object");
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
FAIL("Statement object is still usable");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
/* Any error message is fine, connection should have been killed */
|
|
logMsg(e.what());
|
|
}
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
/* KILL has failed - that is OK, we may not have permissions */
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
|
|
void connection::setTransactionIsolation()
|
|
{
|
|
logMsg("connection::setTransactionIsolation() - MySQL_Connection::setTransactionIsolation()");
|
|
bool have_innodb=false;
|
|
int cant_be_changed_error= -1;
|
|
int server_dependent_insert= -1;
|
|
sql::SQLString query(isMySQL() ? "SHOW VARIABLES LIKE 'transaction_isolation'" : "SHOW VARIABLES LIKE 'tx_isolation'");
|
|
|
|
stmt.reset(con->createStatement());
|
|
try
|
|
{
|
|
con->setTransactionIsolation(sql::TRANSACTION_READ_COMMITTED);
|
|
ASSERT_EQUALS(sql::TRANSACTION_READ_COMMITTED, con->getTransactionIsolation());
|
|
// Should this be transaction_isolation with MySQL servers?
|
|
res.reset(stmt->executeQuery(query));
|
|
checkResultSetScrolling(res);
|
|
res->next();
|
|
ASSERT_EQUALS("READ-COMMITTED", res->getString("Value"));
|
|
|
|
con->setTransactionIsolation(sql::TRANSACTION_READ_UNCOMMITTED);
|
|
ASSERT_EQUALS(sql::TRANSACTION_READ_UNCOMMITTED, con->getTransactionIsolation());
|
|
res.reset(stmt->executeQuery(query));
|
|
res->next();
|
|
ASSERT_EQUALS("READ-UNCOMMITTED", res->getString("Value"));
|
|
|
|
con->setTransactionIsolation(sql::TRANSACTION_REPEATABLE_READ);
|
|
ASSERT_EQUALS(sql::TRANSACTION_REPEATABLE_READ, con->getTransactionIsolation());
|
|
res.reset(stmt->executeQuery(query));
|
|
res->next();
|
|
ASSERT_EQUALS("REPEATABLE-READ", res->getString("Value"));
|
|
|
|
con->setTransactionIsolation(sql::TRANSACTION_SERIALIZABLE);
|
|
ASSERT_EQUALS(sql::TRANSACTION_SERIALIZABLE, con->getTransactionIsolation());
|
|
res.reset(stmt->executeQuery(query));
|
|
res->next();
|
|
ASSERT_EQUALS("SERIALIZABLE", res->getString("Value"));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
try
|
|
{
|
|
con.reset(getConnection());
|
|
stmt.reset(con->createStatement());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
try
|
|
{
|
|
con->setAutoCommit(true);
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT) ENGINE = InnoDB");
|
|
have_innodb=true;
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
have_innodb=false;
|
|
}
|
|
|
|
if (have_innodb)
|
|
{
|
|
try
|
|
{
|
|
con->setAutoCommit(false);
|
|
stmt->execute("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
|
|
stmt->execute("INSERT INTO test(id) VALUES (1)");
|
|
/* JDBC documentation: If this method is called while
|
|
in the middle of a transaction, any changes up to that point
|
|
will be committed.*/
|
|
// setTransactionIsolation does SET SESSION ...
|
|
stmt->execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ");
|
|
// con->setTransactionIsolation(sql::TRANSACTION_REPEATABLE_READ);
|
|
/* According to the JDBC docs the INSERT has been comitted
|
|
and this ROLLBACK must have no impat */
|
|
con->rollback();
|
|
|
|
res.reset(stmt->executeQuery("SELECT COUNT(*) AS _num FROM test"));
|
|
res->next();
|
|
server_dependent_insert=res->getInt("_num");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logMsg("... EXPECTED behaviour - Transaction isolation level can't be changed while a transaction is in progress.");
|
|
logMsg(e.what());
|
|
logMsg("SQLState: " + std::string(e.getSQLState()));
|
|
cant_be_changed_error=e.getErrorCode();
|
|
}
|
|
|
|
try
|
|
{
|
|
con.reset(getConnection());
|
|
stmt.reset(con->createStatement());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
try
|
|
{
|
|
con->setAutoCommit(true);
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT) ENGINE = InnoDB");
|
|
|
|
con->setAutoCommit(false);
|
|
con->setTransactionIsolation(sql::TRANSACTION_SERIALIZABLE);
|
|
stmt->execute("INSERT INTO test(id) VALUES (1)");
|
|
/* JDBC documentation: If this method is called while
|
|
in the middle of a transaction, any changes up to that point
|
|
will be committed.*/
|
|
con->setTransactionIsolation(sql::TRANSACTION_REPEATABLE_READ);
|
|
|
|
if (-1 != cant_be_changed_error)
|
|
{
|
|
FAIL("Changing the transaction level manually has caused an exception. Changing it through API has not!");
|
|
}
|
|
|
|
/* According to the JDBC docs the INSERT has been comitted
|
|
and this ROLLBACK must have no impat */
|
|
con->rollback();
|
|
|
|
res.reset(stmt->executeQuery("SELECT COUNT(*) AS _num FROM test"));
|
|
res->next();
|
|
ASSERT_EQUALS(server_dependent_insert, res->getInt("_num"));
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != cant_be_changed_error)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
else
|
|
{
|
|
logMsg("... EXPECTED behaviour - Transaction isolation level can't be changed while a transaction is in progress.");
|
|
logMsg(e.what());
|
|
logMsg("SQLState: " + std::string(e.getSQLState()));
|
|
}
|
|
}
|
|
}
|
|
|
|
con->close();
|
|
try
|
|
{
|
|
con->setTransactionIsolation(sql::TRANSACTION_READ_COMMITTED);
|
|
FAIL("Closed connection not detected");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
}
|
|
|
|
void connection::rollback()
|
|
{
|
|
try
|
|
{
|
|
con->setAutoCommit(false);
|
|
try
|
|
{
|
|
try
|
|
{
|
|
con->setAutoCommit(true);
|
|
std::unique_ptr<sql::Savepoint> spoint(con->setSavepoint("foo"));
|
|
con->rollback(spoint.get());
|
|
FAIL("autoCommit mode not detected");
|
|
}
|
|
catch (sql::InvalidArgumentException &e)
|
|
{
|
|
ASSERT_EQUALS(e.what(), "The connection is in autoCommit mode");
|
|
}
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
/* no support for savepoints, bad luck... */
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
/* Exploiting bug that different wrapper is currently created if requested for ""
|
|
* and default lib name. just to test that nothing bad happens.
|
|
* Test itself shouldn't fail.
|
|
*/
|
|
#ifndef MYSQLCLIENT_STATIC_BINDING
|
|
|
|
void connection::loadSameLibraryTwice()
|
|
{
|
|
#if defined(_WIN32)
|
|
const sql::SQLString baseName("libmysql.dll");
|
|
#elif defined(__APPLE__)
|
|
const sql::SQLString baseName("libmysqlclient_r.dylib");
|
|
#elif defined(__hpux) && defined(__hppa)
|
|
const sql::SQLString baseName("libmysqlclient_r.sl");
|
|
#else
|
|
const sql::SQLString baseName("libmysqlclient_r.so");
|
|
#endif
|
|
|
|
sql::ConnectOptionsMap connection_properties;
|
|
connection_properties["hostName"]=url;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
connection_properties["useTls"]= useTls? "true" : "false";
|
|
connection_properties["clientlib"]=baseName;
|
|
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Test of the OPT_ENABLE_CLEARTEXT_PLUGIN connection of the text
|
|
The test idea - we try to create fake PAM authorized user and try to connect
|
|
using that user first without, and then with the new option selected. In
|
|
first case the error has to be that cleartext plugin could not be loaded, and
|
|
in second case the error has to be different */
|
|
void connection::enableClearTextAuth()
|
|
{
|
|
int serverVersion=getServerVersion(con);
|
|
|
|
if ( ((serverVersion < 505027) || (serverVersion > 506000)) && (serverVersion < 506007))
|
|
{
|
|
SKIP("The server does not support tested functionality(cleartext plugin enabling)");
|
|
}
|
|
|
|
try
|
|
{
|
|
stmt->executeUpdate("DROP USER 't_ct_user'@'%'");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
// Catching exception if user did not exist
|
|
}
|
|
|
|
try
|
|
{
|
|
stmt->executeUpdate("GRANT ALL ON 't_ct_plugin' TO 't_ct_user' IDENTIFIED WITH "
|
|
"'authentication_pam'");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
SKIP("The authentication_pam plugin not loaded");
|
|
}
|
|
|
|
sql::ConnectOptionsMap opts;
|
|
testsuite::Connection c2;
|
|
|
|
opts["userName"]=sql::SQLString("t_ct_user");
|
|
opts["password"]=sql::SQLString("foo");
|
|
|
|
/*
|
|
Expecting error CR_AUTH_PLUGIN_CANNOT_LOAD_ERROR
|
|
without option ENABLE_CLEARTEXT_PLUGIN
|
|
*/
|
|
try
|
|
{
|
|
c2.reset(getConnection(&opts));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
/* We should have dropped the created user here if assertion fails -
|
|
TODO: Add sort of dropSchemaObject for created users in tearDown */
|
|
ASSERT_EQUALS(2059, e.getErrorCode()/*CR_AUTH_PLUGIN_CANNOT_LOAD_ERROR*/);
|
|
}
|
|
|
|
/*
|
|
Expecting error other then CR_AUTH_PLUGIN_CANNOT_LOAD_ERROR
|
|
as option ENABLE_CLEARTEXT_PLUGIN is used
|
|
*/
|
|
opts["OPT_ENABLE_CLEARTEXT_PLUGIN"]= "true";
|
|
|
|
try
|
|
{
|
|
c2.reset(getConnection(&opts));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
ASSERT(e.getErrorCode() != 2059);
|
|
}
|
|
|
|
stmt->executeUpdate("DROP USER 't_ct_user'@'%'");
|
|
}
|
|
|
|
|
|
void connection::connectAttrAdd()
|
|
{
|
|
logMsg("connection::connectAttr - MYSQL_OPT_CONNECT_ATTR_ADD|MYSQL_OPT_CONNECT_ATTR_DELETE");
|
|
|
|
//TODO: Enable it after fixing
|
|
SKIP("Removed untill fixed(testcase)");
|
|
|
|
#ifdef MISSING_STUFF_SUPPORT_ADDED
|
|
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
std::map< sql::SQLString, sql::SQLString > connectAttrMap;
|
|
std::list< std::string > connectAttrList;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
|
|
connectAttrMap["keyc1"]="value1";
|
|
connectAttrMap["keyc2"]="value2";
|
|
connectAttrMap["keyc3"]="value3";
|
|
connectAttrMap["keyc4"]="value4";
|
|
connectAttrMap["keyc5"]="value5";
|
|
|
|
connectAttrList.push_back(std::string("keyc2"));
|
|
connectAttrList.push_back(std::string("keyc5"));
|
|
|
|
opts.erase("OPT_CONNECT_ATTR_ADD");
|
|
opts.erase("OPT_CONNECT_ATTR_DELETE");
|
|
opts["OPT_CONNECT_ATTR_ADD"]=connectAttrMap;
|
|
opts["OPT_CONNECT_ATTR_DELETE"]=connectAttrList;
|
|
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn1->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT ATTR_NAME, ATTR_VALUE FROM "
|
|
"performance_schema.session_account_connect_attrs WHERE "
|
|
"ATTR_NAME LIKE '%keyc%' ORDER BY ATTR_NAME ASC;"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), "keyc1");
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value1");
|
|
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), "keyc3");
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value3");
|
|
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), "keyc4");
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value4");
|
|
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
|
|
/*
|
|
Check for empty OPT_CONNECT_ATTR_ADD map
|
|
should not result in errors
|
|
*/
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
std::map< sql::SQLString, sql::SQLString > connectAttrMap;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
|
|
opts.erase("OPT_CONNECT_ATTR_ADD");
|
|
opts["OPT_CONNECT_ATTR_ADD"]=connectAttrMap;
|
|
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn1->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT 1"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getInt(1), 1);
|
|
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
|
|
/*
|
|
Check for empty OPT_CONNECT_ATTR_DELETE list
|
|
*/
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
std::map< sql::SQLString, sql::SQLString > connectAttrMap;
|
|
std::list< std::string > connectAttrList;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
|
|
connectAttrMap["keya1"]="value1";
|
|
connectAttrMap["keya2"]="value2";
|
|
|
|
opts.erase("OPT_CONNECT_ATTR_ADD");
|
|
opts.erase("OPT_CONNECT_ATTR_DELETE");
|
|
opts["OPT_CONNECT_ATTR_ADD"]=connectAttrMap;
|
|
opts["OPT_CONNECT_ATTR_DELETE"]=connectAttrList;
|
|
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn1->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT ATTR_NAME, ATTR_VALUE FROM "
|
|
"performance_schema.session_account_connect_attrs WHERE "
|
|
"ATTR_NAME LIKE '%keya%' ORDER BY ATTR_NAME ASC;"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), "keya1");
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value1");
|
|
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), "keya2");
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value2");
|
|
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
/*
|
|
Check with inserting max allowed key-value pair i.e. lesser then size
|
|
of performance_schema_session_connect_attrs_size
|
|
*/
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
int max_count;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn1->createStatement());
|
|
res.reset(stmt->executeQuery("SHOW VARIABLES LIKE "
|
|
"'performance_schema_session_connect_attrs_size';"));
|
|
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getString("Variable_name"), "performance_schema_session_connect_attrs_size");
|
|
int perf_conn_attr_size= res->getInt("Value");
|
|
if (perf_conn_attr_size < 512) {
|
|
SKIP("The performance_schema_session_connect_attrs_size is less then 512");
|
|
} else if (perf_conn_attr_size >= 512 && perf_conn_attr_size < 1024) {
|
|
max_count= 32;
|
|
} else if (perf_conn_attr_size >= 1024 && perf_conn_attr_size < 2048) {
|
|
max_count= 64;
|
|
} else if (perf_conn_attr_size >= 2048) {
|
|
max_count= 128;
|
|
}
|
|
|
|
try
|
|
{
|
|
testsuite::Connection conn2;
|
|
std::map< sql::SQLString, sql::SQLString > connectAttrMap;
|
|
std::list< std::string > connectAttrList;
|
|
std::stringstream skey;
|
|
int i;
|
|
|
|
for (i=1; i <= max_count; ++i) {
|
|
skey.str("");
|
|
skey << "keymu" << i;
|
|
connectAttrMap[skey.str()] = "value";
|
|
}
|
|
|
|
opts.erase("OPT_CONNECT_ATTR_ADD");
|
|
opts.erase("OPT_CONNECT_ATTR_DELETE");
|
|
opts["OPT_CONNECT_ATTR_ADD"]= connectAttrMap;
|
|
|
|
created_objects.clear();
|
|
conn2.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn2->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT ATTR_NAME, ATTR_VALUE FROM "
|
|
"performance_schema.session_account_connect_attrs WHERE "
|
|
"ATTR_NAME LIKE '%keymu%' ORDER BY SUBSTRING(ATTR_NAME, 6)+0 ASC;"));
|
|
|
|
i=0;
|
|
while (res->next()) {
|
|
skey.str("");
|
|
skey << "keymu" << ++i;
|
|
ASSERT_EQUALS(res->getString("ATTR_NAME"), skey.str());
|
|
ASSERT_EQUALS(res->getString("ATTR_VALUE"), "value");
|
|
}
|
|
ASSERT(max_count == i);
|
|
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
#endif // MISSING_STUFF_SUPPORT_ADDED
|
|
}
|
|
|
|
|
|
void connection::connectAttrReset()
|
|
{
|
|
logMsg("connection::connectAttr - MYSQL_OPT_CONNECT_ATTR_RESET");
|
|
|
|
SKIP("Tested functionality is not supported");
|
|
|
|
try
|
|
{
|
|
testsuite::Connection conn2;
|
|
sql::ConnectOptionsMap opts;
|
|
std::map< sql::SQLString, sql::SQLString > connectAttrMap;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
|
|
connectAttrMap["keyd1"]="value1";
|
|
connectAttrMap["keyd2"]="value2";
|
|
connectAttrMap["keyd3"]="value3";
|
|
|
|
opts.erase("OPT_CONNECT_ATTR_ADD");
|
|
#ifdef MISSING_STUFF_SUPPORT_ADDED
|
|
opts["OPT_CONNECT_ATTR_ADD"]=connectAttrMap;
|
|
#endif
|
|
opts["OPT_CONNECT_ATTR_RESET"]=0;
|
|
|
|
created_objects.clear();
|
|
conn2.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn2->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT ATTR_NAME, ATTR_VALUE FROM "
|
|
"performance_schema.session_account_connect_attrs WHERE "
|
|
"ATTR_NAME LIKE '%keyd%' ORDER BY ATTR_NAME ASC;"));
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
|
|
void connection::connectCharsetDir()
|
|
{
|
|
sql::ConnectOptionsMap opts;
|
|
sql::SQLString charDir("/tmp/");
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["useTls"]= useTls? "true" : "false";
|
|
opts["charsetDir"]=charDir;
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(opts));
|
|
|
|
sql::SQLString outDir=con->getClientOption("characterSetDirectory");
|
|
ASSERT_EQUALS(charDir, outDir);
|
|
}
|
|
|
|
|
|
void connection::connectSSLEnforce()
|
|
{
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap opts;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["useTls"]= "true";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(opts));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
ASSERT_EQUALS(2026, e.getErrorCode() /*CR_SSL_CONNECTION_ERROR*/);
|
|
}
|
|
}
|
|
|
|
|
|
void connection::setAuthDir()
|
|
{
|
|
logMsg("connection::setAuthDir - MYSQL_PLUGIN_DIR");
|
|
int serverVersion=getServerVersion(con);
|
|
if ( serverVersion >= 507003 )
|
|
{
|
|
SKIP("Server version >= 5.7.3 needed to run this test");
|
|
}
|
|
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
sql::SQLString in_plugin_dir;
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
#ifdef _WIN32
|
|
in_plugin_dir=sql::SQLString("C:\test_plugin");
|
|
#else
|
|
in_plugin_dir=sql::SQLString("\tmp\test_plugin");
|
|
#endif //_WIN32
|
|
|
|
opts["pluginDir"]=in_plugin_dir;
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
sql::SQLString out_plugin_dir=conn1->getClientOption(sql::SQLString("pluginDir"));
|
|
|
|
ASSERT_EQUALS(in_plugin_dir, out_plugin_dir);
|
|
}
|
|
|
|
|
|
void connection::setDefaultAuth()
|
|
{
|
|
logMsg("connection::setDefaultAuth - MYSQL_DEFAULT_AUTH");
|
|
int serverVersion=getServerVersion(con);
|
|
if ( serverVersion < 507003 )
|
|
{
|
|
SKIP("Server version >= 5.7.3 needed to run this test");
|
|
}
|
|
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
sql::SQLString in_plugin_dir;
|
|
sql::SQLString def_auth("test_set_default_password");
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["useTls"]= useTls? "true" : "false";
|
|
opts["defaultAuth"]=def_auth;
|
|
created_objects.clear();
|
|
|
|
try
|
|
{
|
|
conn1.reset(driver->connect(opts));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
/* With maxscale that happens to be 1105, and does not make sense to test it */
|
|
if (!isMaxScale()) {
|
|
/* Error expected as trying to load unknown authentication plugin */
|
|
ASSERT_EQUALS(2059, e.getErrorCode()/*CR_AUTH_PLUGIN_CANNOT_LOAD_ERROR*/);
|
|
}
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
|
|
void connection::localInfile()
|
|
{
|
|
logMsg("connection::setDefaultAuth - MYSQL_OPT_LOCAL_INFILE");
|
|
|
|
#ifdef _UNIX_
|
|
try
|
|
{
|
|
testsuite::Connection conn1;
|
|
sql::ConnectOptionsMap opts;
|
|
sql::SQLString in_plugin_dir;
|
|
sql::SQLString schema("test");
|
|
std::ofstream infile;
|
|
|
|
infile.open("test_infile.txt");
|
|
infile << "1,\"val1\"\n";
|
|
infile << "2,\"val2\"\n";
|
|
|
|
infile.close();
|
|
|
|
opts["hostName"]=url;
|
|
opts["userName"]=user;
|
|
opts["password"]=passwd;
|
|
opts["schema"]=schema;
|
|
opts["OPT_LOCAL_INFILE"]="1";
|
|
created_objects.clear();
|
|
conn1.reset(driver->connect(opts));
|
|
|
|
stmt.reset(conn1->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test_local_infile");
|
|
stmt->execute("CREATE TABLE test_local_infile(id INT, value VARCHAR(20))");
|
|
stmt->execute("LOAD DATA LOCAL INFILE 'test_infile.txt' "
|
|
"INTO TABLE test_local_infile FIELDS TERMINATED BY ',' OPTIONALLY "
|
|
"ENCLOSED BY '\"' LINES TERMINATED BY '\n'");
|
|
|
|
res.reset(stmt->executeQuery("SELECT * FROM test_local_infile ORDER BY id ASC;"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("1", res->getInt(1));
|
|
ASSERT_EQUALS("val1", res->getString(2));
|
|
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("2", res->getInt(1));
|
|
ASSERT_EQUALS("val2", res->getString(2));
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
#endif //_UNIX_
|
|
}
|
|
|
|
|
|
void connection::isValid()
|
|
{
|
|
logMsg("connection::isValid");
|
|
|
|
try
|
|
{
|
|
if (!con->isValid())
|
|
{
|
|
FAIL("Connection is not active");
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
|
|
void connection::reconnect()
|
|
{
|
|
logMsg("connection::connectOptReconnect - OPT_RECONNECT");
|
|
|
|
logMsg("OPT_RECONNECT disabled");
|
|
try
|
|
{
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]=url;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
connection_properties["OPT_READ_TIMEOUT"]= "1000";
|
|
//connection_properties["socketTimeout"]= "1";
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT sleep(10);"));
|
|
FAIL("Connection didn't timed out");
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
ASSERT(con->reconnect());
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT 1;"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getInt(1), 1);
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
|
|
logMsg("OPT_RECONNECT enabled");
|
|
try
|
|
{
|
|
try
|
|
{
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]=url;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
connection_properties["OPT_READ_TIMEOUT"]="1";
|
|
|
|
connection_properties.erase("OPT_RECONNECT");
|
|
connection_properties["OPT_RECONNECT"]= "true";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SELECT sleep(10);"));
|
|
FAIL("Connection didn't timed out");
|
|
}
|
|
catch (sql::SQLException &/*e*/)
|
|
{
|
|
ASSERT(con->reconnect());
|
|
res.reset(stmt->executeQuery("SELECT 1;"));
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getInt(1), 1);
|
|
}
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void connection::ssl_mode()
|
|
{
|
|
logMsg("connection::ssl_mode - useTls");
|
|
|
|
SKIP("Test needs to be adapted or dropped")
|
|
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]=url;
|
|
connection_properties["userName"]=user;
|
|
connection_properties["password"]=passwd;
|
|
|
|
connection_properties["useTls"] = "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
|
|
res.reset(stmt->executeQuery("SHOW GLOBAL VARIABLES LIKE 'tls_version'"));
|
|
|
|
res->next();
|
|
|
|
std::string tls_versions(res->getString(2));
|
|
|
|
std::cout << "TLS VERSIONS: " <<tls_versions << std::endl;
|
|
|
|
if (tls_versions.empty())
|
|
{
|
|
SKIP("Server doesn't support SSL connections");
|
|
}
|
|
|
|
res.reset(stmt->executeQuery("SHOW SESSION STATUS LIKE 'Ssl_version'"));
|
|
|
|
res->next();
|
|
|
|
ASSERT_EQUALS(0, static_cast<int>(res->getString(2).length()));
|
|
|
|
connection_properties["useTls"] = "true";
|
|
|
|
try
|
|
{
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (std::exception&)
|
|
{
|
|
SKIP("Server doesn't support SSL connections");
|
|
}
|
|
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SHOW SESSION STATUS LIKE 'Ssl_version'"));
|
|
|
|
res->next();
|
|
|
|
ASSERT_GT(0, static_cast<int>(res->getString(2).length()));
|
|
|
|
stmt->execute("Drop user if exists ssluser");
|
|
stmt->execute("CREATE USER 'ssluser' IDENTIFIED BY 'sslpass' require SSL");
|
|
stmt->execute("GRANT all on test.* to 'ssluser'");
|
|
|
|
connection_properties["hostName"]= url;
|
|
connection_properties["userName"]= "ssluser";
|
|
connection_properties["password"]= "sslpass";
|
|
|
|
connection_properties["useTls"]= "true";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
|
|
connection_properties["useTls"]= "false";
|
|
|
|
//only to trigger setssl which changes SSL_MODE
|
|
connection_properties["sslCA"]= "invalid_path";
|
|
|
|
created_objects.clear();
|
|
|
|
try
|
|
{
|
|
con.reset(driver->connect(connection_properties));
|
|
FAIL("User requires SSL");
|
|
} catch (std::exception &e)
|
|
{
|
|
std::cout << e.what() << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
void connection::tls_version()
|
|
{
|
|
logMsg("connection::tls_version - OPT_TLS_VERSION");
|
|
|
|
if (getServerVersion(con) < 1004006)
|
|
{
|
|
SKIP("Server does not support tls_version variable");
|
|
}
|
|
|
|
sql::ConnectOptionsMap connection_properties;
|
|
|
|
connection_properties["hostName"]= url;
|
|
connection_properties["userName"]= user;
|
|
connection_properties["password"]= passwd;
|
|
connection_properties["useTls"]= useTls? "true" : "false";
|
|
|
|
created_objects.clear();
|
|
con.reset(driver->connect(connection_properties));
|
|
|
|
con->setSchema(db);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SHOW GLOBAL VARIABLES LIKE 'tls_version'"));
|
|
|
|
res->next();
|
|
|
|
std::string tls_available(res->getString(2));
|
|
|
|
std::cout << "TLS VERSIONS: " <<tls_available << std::endl;
|
|
|
|
std::vector<std::string> tls_versions;
|
|
|
|
size_t begin_pos = 0;
|
|
|
|
for ( size_t end_pos = tls_available.find_first_of(',',begin_pos);
|
|
begin_pos != std::string::npos || end_pos != std::string::npos;
|
|
begin_pos = end_pos == std::string::npos ? end_pos : end_pos+1,
|
|
end_pos = tls_available.find_first_of(',',begin_pos))
|
|
{
|
|
tls_versions.push_back(tls_available.substr(begin_pos, end_pos-begin_pos));
|
|
}
|
|
|
|
connection_properties["useTls"] = "true";
|
|
|
|
// Using wrong TLS version... should fail to connect
|
|
connection_properties["OPT_TLS_VERSION"] = sql::SQLString("TLSv999");
|
|
|
|
created_objects.clear();
|
|
try
|
|
{
|
|
con.reset(driver->connect(connection_properties));
|
|
SKIP("The tested option(name) is not supported")
|
|
FAIL("Wrong TLS version used and still can connect!");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
//Should FAIL to connect
|
|
}
|
|
|
|
for (std::vector<std::string>::const_iterator version = tls_versions.begin();
|
|
version != tls_versions.end();
|
|
++version)
|
|
{
|
|
connection_properties["OPT_TLS_VERSION"] = sql::SQLString(*version);
|
|
|
|
created_objects.clear();
|
|
try
|
|
{
|
|
con.reset(driver->connect(connection_properties));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
//Server exports TLS_VERSION even if no certs installed...
|
|
//So skipping anyway if error on connect
|
|
std::cout << "SKIP "<< *version << ": " << e.what() << std::endl;
|
|
continue;
|
|
}
|
|
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SHOW SESSION STATUS LIKE 'Ssl_version'"));
|
|
|
|
res->next();
|
|
|
|
ASSERT_EQUALS(*version, res->getString(2));
|
|
}
|
|
}
|
|
|
|
/* With MariaDB C/C this test doesn't have much sense as we don't have option to request the public key, but do this
|
|
* implicitly when needed. The test idea was to show that when the key is already cached the connection will work even
|
|
* w/out (explicit) request for the key
|
|
*/
|
|
void connection::cached_sha2_auth()
|
|
{
|
|
logMsg("connection::auth - MYSQL_OPT_GET_SERVER_PUBLIC_KEY");
|
|
|
|
if (!isMySQL())
|
|
{
|
|
SKIP("Server doesn't support caching_sha2_password");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
stmt->execute("DROP USER 'doomuser'@'%';");
|
|
} catch (...) {}
|
|
|
|
stmt->execute("CREATE USER 'doomuser'@'%' IDENTIFIED WITH caching_sha2_password BY '!sha2user_pass'");
|
|
stmt->execute("GRANT ALL ON " + db + ".* TO 'doomuser'@'%'");
|
|
|
|
sql::ConnectOptionsMap opts;
|
|
opts["hostName"]= url;
|
|
opts["userName"]= "doomuser";
|
|
opts["password"]= "!sha2user_pass";
|
|
opts["serverRsaPublicKeyFile"]= "test_mysql_server.pem";
|
|
opts["useTls"]= "false";
|
|
|
|
try {
|
|
|
|
// Should fail using unencrypted connection, since we don't have server
|
|
// public key
|
|
created_objects.clear();
|
|
//need to close connection, otherwise will use fast auth!
|
|
con->close();
|
|
// we can't really know, if we used the key from the given file :/
|
|
con.reset(driver->connect(opts));
|
|
}
|
|
catch(std::exception &/*e*/)
|
|
{
|
|
FAIL("Could not establish connection");
|
|
}
|
|
|
|
//Now reconnection, but we can't really know if it uses cached key
|
|
con->close();
|
|
con.reset(driver->connect(opts));
|
|
|
|
// Cleanup
|
|
con.reset(getConnection());
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP USER 'doomuser'@'%';");
|
|
}
|
|
|
|
void connection::bugConCpp21()
|
|
{
|
|
sql::Properties p;
|
|
|
|
p["user"]= user;
|
|
|
|
con.reset(driver->connect(url + "?user=wronguser&password=" + passwd + "&useTls=true", p));
|
|
ASSERT(con.get() != nullptr);
|
|
stmt.reset(con->createStatement());
|
|
res.reset(stmt->executeQuery("SHOW STATUS LIKE 'Ssl_cipher'"));
|
|
ASSERT(res->next());
|
|
logMsg("Connection cipher:" + res->getString(2));
|
|
}
|
|
|
|
|
|
void connection::unknownPropertyConnect()
|
|
{
|
|
sql::Properties p;
|
|
|
|
p["user"]= user;
|
|
p["useTls"] = useTls ? "true" : "false";
|
|
|
|
con.reset(driver->connect(url + "?password=" + passwd + "¬ExistentPropery=blahblah", p));
|
|
ASSERT(con.get());
|
|
p["hostName"]= url;
|
|
p["password"]= passwd;
|
|
p["notExistentPropery"]= "blahblah";
|
|
con.reset(driver->connect(p));
|
|
ASSERT(con.get());
|
|
}
|
|
|
|
void checkCharsetVariables(sql::Connection* con, const sql::SQLString& charset)
|
|
{
|
|
testsuite::Statement st(con->createStatement());
|
|
testsuite::ResultSet rs(st->executeQuery("select @@character_set_client, @@character_set_connection, @@character_set_results"));
|
|
|
|
ASSERT(rs->next());
|
|
ASSERT_EQUALS(charset, rs->getString(1));
|
|
ASSERT_EQUALS(charset, rs->getString(2));
|
|
ASSERT_EQUALS(charset, rs->getString(3));
|
|
}
|
|
|
|
void connection::useCharacterSet()
|
|
{
|
|
sql::Properties p;
|
|
const sql::SQLString utf8mb4("utf8mb4");
|
|
|
|
p["user"]= user;
|
|
p["password"]= passwd;
|
|
p["useTls"] = useTls ? "true" : "false";
|
|
|
|
con.reset(driver->connect(url + "?useCharacterEncoding=utf8", p));
|
|
ASSERT(con.get());
|
|
checkCharsetVariables(con.get(), utf8mb4);
|
|
p["hostName"]= url;
|
|
p["useCharacterEncoding"]= "utf8";
|
|
con.reset(driver->connect(p));
|
|
ASSERT(con.get());
|
|
checkCharsetVariables(con.get(), utf8mb4);
|
|
p["useCharacterEncoding"] = "boguscs";
|
|
try
|
|
{
|
|
con.reset(driver->connect(p));
|
|
FAIL("Exception was expected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
// All is fine
|
|
}
|
|
}
|
|
|
|
|
|
void connection::concpp94_loadLocalInfile()
|
|
{
|
|
sql::Properties p;
|
|
sql::SQLString onServer(getVariableValue("local_infile", true));
|
|
|
|
if (onServer.compare("0") == 0) {
|
|
try {
|
|
setVariableValue("local_infile", "ON", true); // can't be session
|
|
}
|
|
catch (sql::SQLException&) {
|
|
SKIP("local_infile is OFF at the server, and test could not change that. Doesn't make sense to continue the test");
|
|
}
|
|
}
|
|
|
|
p["user"] = user;
|
|
p["password"] = passwd;
|
|
p["allowLocalInfile"] = "true";
|
|
p["useTls"] = useTls ? "true" : "false";
|
|
|
|
con.reset(driver->connect(url, p));
|
|
ASSERT(con.get());
|
|
stmt.reset(con->createStatement());
|
|
|
|
try {
|
|
stmt->execute("LOAD DATA LOCAL INFILE 'nonexistent.txt' INTO TABLE nonexistent(b)");
|
|
}
|
|
catch (sql::SQLException& e) {
|
|
if (e.getErrorCode() == 1148 || e.getErrorCode() == 4166) {
|
|
printf("\n# ERR: Caught sql::SQLException at ::%d [%s] (%d/%s)\n", __LINE__, e.what(), e.getErrorCode(), e.getSQLStateCStr());
|
|
printf("# ");
|
|
FAIL("Wrong error code - local infile is still not allowed");
|
|
}
|
|
//ASSERT(4166!=e.getErrorCode());
|
|
ASSERT_EQUALS("42S02", e.getSQLState());
|
|
}
|
|
}
|
|
|
|
|
|
void connection::concpp105_conn_concurrency()
|
|
{
|
|
sql::Properties p{{"user", user}, {"password", passwd}};
|
|
std::vector<std::function<void()>> t1cbs;
|
|
std::vector<std::function<void()>> t2cbs;
|
|
|
|
/* There is no sense to test this against SkySQL and diatant servers in general */
|
|
if (std::getenv("SKYSQL") != nullptr || std::getenv("SKYSQL_HA") != nullptr) {
|
|
SKIP("It's not necessary to run this test against SkySQL");
|
|
}
|
|
for (int i = 0; i < 500; i++) {
|
|
t1cbs.push_back([&] {
|
|
std::unique_ptr<sql::Connection> conn(driver->connect(url, p));
|
|
//std::cout << "# t1:" << conn->getHostname().c_str() << std::endl;
|
|
});
|
|
|
|
t2cbs.push_back([&] {
|
|
std::unique_ptr<sql::Connection> conn(driver->connect(url, p));
|
|
//std::cout << "# t2:" << conn->getHostname().c_str() << std::endl;
|
|
});
|
|
}
|
|
|
|
std::thread t1([&] {
|
|
for (auto& cb : t1cbs)
|
|
cb();
|
|
});
|
|
std::thread t2([&] {
|
|
for (auto& cb : t2cbs)
|
|
cb();
|
|
});
|
|
|
|
t1.join();
|
|
t2.join();
|
|
}
|
|
|
|
/* Test of setting of connection attributes */
|
|
void connection::concpp112_connection_attributes()
|
|
{
|
|
if (!perfschemaEnabled)
|
|
{
|
|
SKIP("Test requires performance_schema to be on");
|
|
}
|
|
pstmt.reset(con->prepareStatement("SELECT ATTR_VALUE FROM performance_schema.session_connect_attrs "
|
|
"WHERE processlist_id=CONNECTION_ID() AND ATTR_NAME=?"));
|
|
pstmt->setString(1, "_client_name2");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("maconcpp", res->getString(1));
|
|
res->close();
|
|
pstmt->setString(1, "_client_version2");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(driverVersion, res->getString(1));
|
|
res->close();
|
|
|
|
sql::Properties p{{"user", user}, {"password", passwd}};
|
|
sql::SQLString localUrl(url);
|
|
localUrl.append("?connectionAttributes=_client_attr1: attr1_value , _client_attr2 :attr2_value");
|
|
|
|
con.reset(driver->connect(localUrl, p));
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT ATTR_VALUE FROM performance_schema.session_connect_attrs "
|
|
"WHERE processlist_id=CONNECTION_ID() AND ATTR_NAME=?"));
|
|
pstmt->setString(1, "_client_attr1");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("attr1_value", res->getString(1));
|
|
res->close();
|
|
pstmt->setString(1, "_client_attr2");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("attr2_value", res->getString(1));
|
|
res->close();
|
|
|
|
con->close();
|
|
|
|
localUrl= url;
|
|
p.emplace("connectionAttributes", "_client_attr12, _client_attr22: attr2_value2");
|
|
con.reset(driver->connect(localUrl, p));
|
|
pstmt.reset(con->prepareStatement("SELECT ATTR_VALUE FROM performance_schema.session_connect_attrs "
|
|
"WHERE processlist_id=CONNECTION_ID() AND ATTR_NAME=?"));
|
|
pstmt->setString(1, "_client_attr22");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("attr2_value2", res->getString(1));
|
|
res->close();
|
|
pstmt->setString(1, "_client_attr12");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(!res->next());
|
|
//ASSERT(res->next());
|
|
///* Not sure why, but setting attribute with name, but without value results in blank space value of the attribute(with Windows client) */
|
|
//ASSERT_EQUALS(" ", my_fetch_str(Hstmt, buffer, 1), 2);
|
|
|
|
p["connectionAttributes"]= "_client_attr13 :attr1_value3, _client_attr23 ";
|
|
con.reset(driver->connect(localUrl, p));
|
|
pstmt.reset(con->prepareStatement("SELECT ATTR_VALUE FROM performance_schema.session_connect_attrs "
|
|
"WHERE processlist_id=CONNECTION_ID() AND ATTR_NAME=?"));
|
|
pstmt->setString(1, "_client_attr13");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("attr1_value3", res->getString(1));
|
|
res->close();
|
|
pstmt->setString(1, "_client_attr23");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(!res->next());
|
|
/*ASSERT(res->next());
|
|
ASSERT_EQUALS(" ", my_fetch_str(Hstmt, buffer, 1), 2);*/
|
|
|
|
p["connectionAttributes"]= "_client_attr14";
|
|
con.reset(driver->connect(localUrl, p));
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT ATTR_VALUE FROM performance_schema.session_connect_attrs "
|
|
"WHERE processlist_id=CONNECTION_ID() AND ATTR_NAME=?"));
|
|
pstmt->setString(1, "_client_attr14");
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(!res->next());
|
|
/*ASSERT(res->next());
|
|
ASSERT_EQUALS(" ", res->getString(1));*/
|
|
|
|
pstmt.reset();
|
|
con.reset();
|
|
}
|
|
|
|
void connection::setUp()
|
|
{
|
|
super::setUp();
|
|
|
|
std::unique_ptr<sql::DatabaseMetaData> meta(con->getMetaData());
|
|
driverVersion= meta->getDriverVersion();
|
|
|
|
res.reset(stmt->executeQuery("SELECT 1 FROM dual where @@performance_schema=1"));
|
|
perfschemaEnabled= res->next();
|
|
|
|
res.reset();
|
|
stmt.reset(con->createStatement());
|
|
}
|
|
|
|
} /* namespace connection */
|
|
} /* namespace testsuite */
|