Add SqlResultSet

parent 0d514c93
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef ATRT_CLIENT_HPP
#define ATRT_CLIENT_HPP
#include <DbUtil.hpp>
class AtrtClient: public DbUtil {
public:
enum AtrtCommandType {
ATCT_CHANGE_VERSION= 1,
ATCT_RESET_PROC= 2
};
AtrtClient(const char* _user= "root",
const char* _password= "",
const char* _suffix= ".1.atrt");
AtrtClient(MYSQL*);
~AtrtClient();
// Command functions
bool changeVersion(int process_id, const char* process_args);
bool resetProc(int process_id);
// Query functions
bool getConnectString(int cluster_id, SqlResultSet& result);
bool getClusters(SqlResultSet& result);
bool getMgmds(int cluster_id, SqlResultSet& result);
bool getNdbds(int cluster_id, SqlResultSet& result);
private:
int writeCommand(AtrtCommandType _type,
const Properties& args);
bool readCommand(uint command_id,
SqlResultSet& result);
bool doCommand(AtrtCommandType _type,
const Properties& args);
};
#endif
...@@ -19,14 +19,11 @@ ...@@ -19,14 +19,11 @@
#ifndef DBUTIL_HPP #ifndef DBUTIL_HPP
#define DBUTIL_HPP #define DBUTIL_HPP
#include <time.h> #include <NDBT.hpp>
#include <stdio.h> #include <BaseString.hpp>
#include <string.h> #include <Properties.hpp>
#include <Vector.hpp>
#include <mysql.h> #include <mysql.h>
//include "rand.h"
#include <stdlib.h>
#include "BaseString.hpp"
#include "NDBT.hpp"
//#define DEBUG //#define DEBUG
#define DIE_UNLESS(expr) \ #define DIE_UNLESS(expr) \
...@@ -49,6 +46,41 @@ if (r) \ ...@@ -49,6 +46,41 @@ if (r) \
DIE_UNLESS(r == 0);\ DIE_UNLESS(r == 0);\
} }
class SqlResultSet : public Properties {
public:
// Get row with number
bool get_row(int row_num);
// Load next row
bool next(void);
// Reset iterator
void reset(void);
// Remove current row from resultset
void remove();
SqlResultSet();
~SqlResultSet();
const char* column(const char* col_name);
uint columnAsInt(const char* col_name);
uint insertId();
uint affectedRows();
uint numRows(void);
uint mysqlErrno();
const char* mysqlError();
const char* mysqlSqlstate();
private:
uint get_int(const char* name);
const char* get_string(const char* name);
const Properties* m_curr_row;
uint m_curr_row_num;
};
#define DBU_FAILED 1 #define DBU_FAILED 1
#define DBU_OK 0 #define DBU_OK 0
...@@ -56,11 +88,23 @@ class DbUtil ...@@ -56,11 +88,23 @@ class DbUtil
{ {
public: public:
/* Deprecated, see DbUtil(dbname, suffix) */ DbUtil(MYSQL* mysql);
DbUtil(const char * databaseName); DbUtil(const char* dbname = "mysql",
DbUtil(const char* dbname, const char* suffix = NULL); const char* user = "root",
const char* pass = "",
const char* suffix = NULL);
~DbUtil(); ~DbUtil();
bool doQuery(const char* query);
bool doQuery(const char* query, SqlResultSet& result);
bool doQuery(const char* query, const Properties& args, SqlResultSet& result);
bool doQuery(BaseString& str);
bool doQuery(BaseString& str, SqlResultSet& result);
bool doQuery(BaseString& str, const Properties& args, SqlResultSet& result);
bool waitConnected(int timeout);
/* Deprecated, see connect() */ /* Deprecated, see connect() */
void databaseLogin(const char * system, void databaseLogin(const char * system,
const char * usr, const char * usr,
...@@ -74,25 +118,35 @@ public: ...@@ -74,25 +118,35 @@ public:
const char * getPassword(){return m_pass.c_str();}; const char * getPassword(){return m_pass.c_str();};
const char * getHost() {return m_host.c_str();}; const char * getHost() {return m_host.c_str();};
const char * getSocket() {return m_socket.c_str();}; const char * getSocket() {return m_socket.c_str();};
const char * getServerType(){return mysql_get_server_info(mysql);}; const char * getServerType(){return mysql_get_server_info(m_mysql);};
const char * getError(); const char * getError();
MYSQL * getMysql(){return mysql;}; MYSQL * getMysql(){return m_mysql;};
MYSQL_STMT * STDCALL mysqlSimplePrepare(const char *query); MYSQL_STMT * STDCALL mysqlSimplePrepare(const char *query);
void databaseLogout(); void databaseLogout();
void mysqlCloseStmHandle(MYSQL_STMT *my_stmt); void mysqlCloseStmHandle(MYSQL_STMT *my_stmt);
int connect(); int connect();
void disconnect();
int selectDb(); int selectDb();
int selectDb(const char *); int selectDb(const char *);
int createDb(BaseString&); int createDb(BaseString&);
int doQuery(BaseString&);
int doQuery(const char *);
int getErrorNumber(); int getErrorNumber();
unsigned long selectCountTable(const char * table); unsigned long selectCountTable(const char * table);
protected:
bool runQuery(const char* query,
const Properties& args,
SqlResultSet& rows);
bool isConnected();
MYSQL * m_mysql;
bool m_free_mysql; /* Don't free mysql* if allocated elsewhere */
private: private:
bool m_connected; bool m_connected;
...@@ -102,15 +156,11 @@ private: ...@@ -102,15 +156,11 @@ private:
BaseString m_pass; // MySQL User Password BaseString m_pass; // MySQL User Password
BaseString m_dbname; // Database to use BaseString m_dbname; // Database to use
BaseString m_socket; // MySQL Server Unix Socket BaseString m_socket; // MySQL Server Unix Socket
BaseString default_file; BaseString m_default_file;
BaseString default_group; BaseString m_default_group;
unsigned int m_port; // MySQL Server port unsigned int m_port; // MySQL Server port
MYSQL * mysql;
MYSQL_RES * m_result;
MYSQL_ROW m_row;
void setDbName(const char * name){m_dbname.assign(name);}; void setDbName(const char * name){m_dbname.assign(name);};
void setUser(const char * user_name){m_user.assign(user_name);}; void setUser(const char * user_name){m_user.assign(user_name);};
void setPassword(const char * password){m_pass.assign(password);}; void setPassword(const char * password){m_pass.assign(password);};
......
...@@ -53,6 +53,7 @@ DbCreate DbAsyncGenerator \ ...@@ -53,6 +53,7 @@ DbCreate DbAsyncGenerator \
testSRBank \ testSRBank \
test_event_merge \ test_event_merge \
testIndexStat \ testIndexStat \
testNDBT \
NdbRepStress NdbRepStress
EXTRA_PROGRAMS = \ EXTRA_PROGRAMS = \
...@@ -99,6 +100,8 @@ ndbapi_slow_select_SOURCES = slow_select.cpp ...@@ -99,6 +100,8 @@ ndbapi_slow_select_SOURCES = slow_select.cpp
testReadPerf_SOURCES = testReadPerf.cpp testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp testLcp_SOURCES = testLcp.cpp
testPartitioning_SOURCES = testPartitioning.cpp testPartitioning_SOURCES = testPartitioning.cpp
testNDBT_SOURCES = testNDBT.cpp
testNDBT_LDADD = $(LDADD) $(top_srcdir)/libmysql_r/libmysqlclient_r.la
testBitfield_SOURCES = testBitfield.cpp testBitfield_SOURCES = testBitfield.cpp
NdbRepStress_SOURCES = acrt/NdbRepStress.cpp NdbRepStress_SOURCES = acrt/NdbRepStress.cpp
DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
......
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <NDBT.hpp>
#include <NDBT_Test.hpp>
#include <DbUtil.hpp>
#include <AtrtClient.hpp>
int runTestAtrtClient(NDBT_Context* ctx, NDBT_Step* step){
AtrtClient atrt;
SqlResultSet clusters;
if (!atrt.getClusters(clusters))
return NDBT_FAILED;
int i= 0;
while(clusters.next())
{
ndbout << clusters.column("name") << endl;
if (i++ == 1){
ndbout << "removing: " << clusters.column("name") << endl;
clusters.remove();
}
}
clusters.reset();
while(clusters.next())
{
ndbout << clusters.column("name") << endl;
}
return NDBT_OK;
}
int runTestDbUtil(NDBT_Context* ctx, NDBT_Step* step){
DbUtil sql;
{
// Select all rows from mysql.user
SqlResultSet result;
if (!sql.doQuery("SELECT * FROM mysql.user", result))
return NDBT_FAILED;
// result.print();
while(result.next())
{
ndbout << result.column("host") << ", "
<< result.column("uSer") << ", "
<< result.columnAsInt("max_updates") << ", "
<< endl;
}
result.reset();
while(result.next())
{
ndbout << result.column("host") << endl;
}
}
{
// No column name, query should fail
Properties args;
SqlResultSet result;
if (sql.doQuery("SELECT * FROM mysql.user WHERE name=?", args, result))
return NDBT_FAILED;
result.print();
}
{
// Select nonexisiting rows from mysql.user
Properties args;
SqlResultSet result;
args.put("0", "no_such_host");
if (!sql.doQuery("SELECT * FROM mysql.user WHERE host=?", args, result))
return NDBT_FAILED;
ndbout << "no rows" << endl;
result.print();
// Change args to an find one row
args.clear();
args.put("0", "localhost");
if (!sql.doQuery("SELECT host, user FROM mysql.user WHERE host=?",
args, result))
return NDBT_FAILED;
result.print();
}
{
if (!sql.doQuery("CREATE TABLE sql_client_test (a int, b varchar(255))"))
return NDBT_FAILED;
if (!sql.doQuery("INSERT INTO sql_client_test VALUES(1, 'hello'), (2, 'bye')"))
return NDBT_FAILED;
// Select all rows from sql_client_test
SqlResultSet result;
if (!sql.doQuery("SELECT * FROM sql_client_test", result))
return NDBT_FAILED;
// result.print();
while(result.next())
{
}
// Select second row from sql_client_test
Properties args;
args.put("0", 2);
if (!sql.doQuery("SELECT * FROM sql_client_test WHERE a=?", args,result))
return NDBT_FAILED;
result.print();
result.reset();
while(result.next())
{
ndbout << "a: " << result.columnAsInt("a") << endl;
ndbout << "b: " << result.column("b") << endl;
if (result.columnAsInt("a") != 2){
ndbout << "hepp1" << endl;
return NDBT_FAILED;
}
if (strcmp(result.column("b"), "bye")){
ndbout << "hepp2" << endl;
return NDBT_FAILED;
}
}
if (sql.selectCountTable("sql_client_test") != 2)
{
ndbout << "Got wrong count" << endl;
return NDBT_FAILED;
}
if (!sql.doQuery("DROP TABLE sql_client_test"))
return NDBT_FAILED;
}
return NDBT_OK;
}
NDBT_TESTSUITE(testNDBT);
TESTCASE("AtrtClient",
"Test AtrtClient class"){
INITIALIZER(runTestAtrtClient);
}
TESTCASE("DbUtil",
"Test DbUtil class"){
INITIALIZER(runTestDbUtil);
}
NDBT_TESTSUITE_END(testNDBT);
int main(int argc, const char** argv){
ndb_init();
return testNDBT.execute(argc, argv);
}
/* Copyright (C) 2008 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <AtrtClient.hpp>
#include <NDBT_Output.hpp>
#include <NdbSleep.h>
AtrtClient::AtrtClient(const char* _user,
const char* _password,
const char* _group_suffix)
: DbUtil(_user, _password, _group_suffix)
{
}
AtrtClient::AtrtClient(MYSQL* mysql)
: DbUtil(mysql)
{
}
AtrtClient::~AtrtClient(){
}
int
AtrtClient::writeCommand(AtrtCommandType _type,
const Properties& args){
if (!isConnected())
return false;
BaseString sql;
sql.assfmt("INSERT command ( ");
const char* name;
{
Properties::Iterator iter(&args);
while((name= iter.next())){
sql.appfmt("%s, ", name);
}
}
sql.appfmt(" state, cmd) VALUES (");
{
Properties::Iterator iter(&args);
while((name= iter.next())){
PropertiesType t;
Uint32 val_i;
BaseString val_s;
args.getTypeOf(name, &t);
switch(t) {
case PropertiesType_Uint32:
args.get(name, &val_i);
sql.appfmt("%d, ", val_i);
break;
case PropertiesType_char:
args.get(name, val_s);
sql.appfmt("'%s', ", val_s.c_str());
break;
default:
assert(false);
break;
}
}
}
sql.appfmt("'new', %d)", _type);
if (!doQuery(sql)){
return -1;
}
return mysql_insert_id(m_mysql);
}
bool
AtrtClient::readCommand(uint command_id,
SqlResultSet& result){
Properties args;
args.put("0", command_id);
return runQuery("SELECT * FROM command WHERE id = ?",
args,
result);
}
bool
AtrtClient::doCommand(AtrtCommandType type,
const Properties& args){
int running_timeout= 10;
int total_timeout= 120;
int commandId= writeCommand(type,
args);
if (commandId == -1){
g_err << "Failed to write command" << endl;
return false;
}
while (true){
SqlResultSet result;
if (!readCommand(commandId, result))
{
result.print();
g_err << "Failed to read command "<< commandId << endl;
return false;
}
// Get first row
result.next();
// Check if command has completed
BaseString state(result.column("state"));
if (state == "done") {
return true;
}
if (state == "new"){
if (!running_timeout--){
g_err << "Timeout while waiting for command "
<< commandId << " to start run" << endl;
return false;
}
}
else if (!total_timeout--){
g_err << "Timeout while waiting for result of command "
<< commandId << endl;
return false;
}
NdbSleep_SecSleep(1);
}
return false;
}
bool
AtrtClient::changeVersion(int process_id,
const char* process_args){
Properties args;
args.put("process_id", process_id);
args.put("process_args", process_args);
return doCommand(ATCT_CHANGE_VERSION, args);
}
bool
AtrtClient::resetProc(int process_id){
Properties args;
args.put("process_id", process_id);
return doCommand(ATCT_RESET_PROC, args);
}
bool
AtrtClient::getConnectString(int cluster_id, SqlResultSet& result){
Properties args;
args.put("0", cluster_id);
return doQuery("SELECT value as connectstring " \
"FROM cluster c, process p, host h, options o " \
"WHERE c.id=p.cluster_id AND p.host_id=h.id AND " \
"p.id=o.process_id AND c.id=? AND " \
"o.name='--ndb-connectstring=' AND type='ndb_mgmd'",
args,
result);
}
bool
AtrtClient::getClusters(SqlResultSet& result){
Properties args;
return runQuery("SELECT id, name FROM cluster WHERE name != '.atrt'",
args,
result);
}
bool
AtrtClient::getMgmds(int cluster_id, SqlResultSet& result){
Properties args;
args.put("0", cluster_id);
return runQuery("SELECT * FROM process WHERE cluster_id=? and type='ndb_mgmd'",
args,
result);
}
bool
AtrtClient::getNdbds(int cluster_id, SqlResultSet& result){
Properties args;
args.put("0", cluster_id);
return runQuery("SELECT * FROM process WHERE cluster_id=? and type='ndbd'",
args,
result);
}
/* Copyright (C) 2007 MySQL AB /* Copyright (C) 2008 MySQL AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -16,43 +16,89 @@ ...@@ -16,43 +16,89 @@
/* DbUtil.cpp: implementation of the database utilities class.*/ /* DbUtil.cpp: implementation of the database utilities class.*/
#include "DbUtil.hpp" #include "DbUtil.hpp"
#include <NdbSleep.h>
/* Constructors */
DbUtil::DbUtil(const char * dbname) /* Constructors */
{
m_port = 0;
m_connected = false;
this->setDbName(dbname);
}
DbUtil::DbUtil(const char * dbname, const char* suffix) DbUtil::DbUtil(const char* _dbname,
const char* _user,
const char* _password,
const char* _suffix):
m_connected(false),
m_dbname(_dbname),
m_mysql(NULL),
m_free_mysql(true)
{ {
this->setDbName(dbname);
m_connected = false;
const char* env= getenv("MYSQL_HOME"); const char* env= getenv("MYSQL_HOME");
if (env && strlen(env)) if (env && strlen(env))
{ {
default_file.assfmt("%s/my.cnf", env); m_default_file.assfmt("%s/my.cnf", env);
} }
if (suffix != NULL){ if (_suffix != NULL){
default_group.assfmt("client%s", suffix); m_default_group.assfmt("client%s", _suffix);
} }
else { else {
default_group.assign("client.1.master"); m_default_group.assign("client.1.master");
}
ndbout << "default_file: " << m_default_file.c_str() << endl;
ndbout << "default_group: " << m_default_group.c_str() << endl;
m_user.assign(_user);
m_pass.assign(_password);
}
DbUtil::DbUtil(MYSQL* mysql):
m_connected(true),
m_mysql(mysql),
m_free_mysql(false)
{
}
bool
DbUtil::isConnected(){
if (m_connected == true)
{
assert(m_mysql);
return true;
}
return connect() == 0;
}
bool
DbUtil::waitConnected(int timeout) {
timeout*= 10;
while(!isConnected()){
if (timeout-- == 0)
return false;
NdbSleep_MilliSleep(100);
} }
return true;
}
ndbout << "default_file: " << default_file.c_str() << endl; void
ndbout << "default_group: " << default_group.c_str() << endl; DbUtil::disconnect(){
if (m_mysql != NULL){
if (m_free_mysql)
mysql_close(m_mysql);
m_mysql= NULL;
}
m_connected = false;
} }
/* Destructor*/
/* Destructor */
DbUtil::~DbUtil() DbUtil::~DbUtil()
{ {
this->databaseLogout(); disconnect();
} }
/* Database Login */ /* Database Login */
...@@ -62,18 +108,18 @@ DbUtil::databaseLogin(const char* system, const char* usr, ...@@ -62,18 +108,18 @@ DbUtil::databaseLogin(const char* system, const char* usr,
const char* password, unsigned int portIn, const char* password, unsigned int portIn,
const char* sockIn, bool transactional) const char* sockIn, bool transactional)
{ {
if (!(mysql = mysql_init(NULL))) if (!(m_mysql = mysql_init(NULL)))
{ {
myerror("DB Login-> mysql_init() failed"); myerror("DB Login-> mysql_init() failed");
exit(DBU_FAILED); exit(DBU_FAILED);
} }
this->setUser(usr); setUser(usr);
this->setHost(system); setHost(system);
this->setPassword(password); setPassword(password);
this->setPort(portIn); setPort(portIn);
this->setSocket(sockIn); setSocket(sockIn);
if (!(mysql_real_connect(mysql, if (!(mysql_real_connect(m_mysql,
m_host.c_str(), m_host.c_str(),
m_user.c_str(), m_user.c_str(),
m_pass.c_str(), m_pass.c_str(),
...@@ -82,24 +128,24 @@ DbUtil::databaseLogin(const char* system, const char* usr, ...@@ -82,24 +128,24 @@ DbUtil::databaseLogin(const char* system, const char* usr,
m_socket.c_str(), 0))) m_socket.c_str(), 0)))
{ {
myerror("connection failed"); myerror("connection failed");
mysql_close(mysql); mysql_close(m_mysql);
exit(DBU_FAILED); exit(DBU_FAILED);
} }
mysql->reconnect = TRUE; m_mysql->reconnect = TRUE;
/* set AUTOCOMMIT */ /* set AUTOCOMMIT */
if(!transactional) if(!transactional)
mysql_autocommit(mysql, TRUE); mysql_autocommit(m_mysql, TRUE);
else else
mysql_autocommit(mysql, FALSE); mysql_autocommit(m_mysql, FALSE);
#ifdef DEBUG #ifdef DEBUG
printf("\n\tConnected to MySQL server version: %s (%lu)\n\n", printf("\n\tConnected to MySQL server version: %s (%lu)\n\n",
mysql_get_server_info(mysql), mysql_get_server_info(m_mysql),
(unsigned long) mysql_get_server_version(mysql)); (unsigned long) mysql_get_server_version(m_mysql));
#endif #endif
this->selectDb(); selectDb();
} }
/* Database Connect */ /* Database Connect */
...@@ -107,15 +153,15 @@ DbUtil::databaseLogin(const char* system, const char* usr, ...@@ -107,15 +153,15 @@ DbUtil::databaseLogin(const char* system, const char* usr,
int int
DbUtil::connect() DbUtil::connect()
{ {
if (!(mysql = mysql_init(NULL))) if (!(m_mysql = mysql_init(NULL)))
{ {
myerror("DB connect-> mysql_init() failed"); myerror("DB connect-> mysql_init() failed");
return DBU_FAILED; return DBU_FAILED;
} }
/* Load connection parameters file and group */ /* Load connection parameters file and group */
if (mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, default_file.c_str()) || if (mysql_options(m_mysql, MYSQL_READ_DEFAULT_FILE, m_default_file.c_str()) ||
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, default_group.c_str())) mysql_options(m_mysql, MYSQL_READ_DEFAULT_GROUP, m_default_group.c_str()))
{ {
myerror("DB Connect -> mysql_options failed"); myerror("DB Connect -> mysql_options failed");
return DBU_FAILED; return DBU_FAILED;
...@@ -126,14 +172,14 @@ DbUtil::connect() ...@@ -126,14 +172,14 @@ DbUtil::connect()
NOTE! user and password can be stored there as well NOTE! user and password can be stored there as well
*/ */
if (mysql_real_connect(mysql, NULL, "root","", m_dbname.c_str(), if (mysql_real_connect(m_mysql, NULL, "root","", m_dbname.c_str(),
0, NULL, 0) == NULL) 0, NULL, 0) == NULL)
{ {
myerror("connection failed"); myerror("connection failed");
mysql_close(mysql); mysql_close(m_mysql);
return DBU_FAILED; return DBU_FAILED;
} }
this->selectDb(); selectDb();
m_connected = true; m_connected = true;
return DBU_OK; return DBU_OK;
} }
...@@ -144,11 +190,11 @@ DbUtil::connect() ...@@ -144,11 +190,11 @@ DbUtil::connect()
void void
DbUtil::databaseLogout() DbUtil::databaseLogout()
{ {
if (mysql){ if (m_mysql){
#ifdef DEBUG #ifdef DEBUG
printf("\n\tClosing the MySQL database connection ...\n\n"); printf("\n\tClosing the MySQL database connection ...\n\n");
#endif #endif
mysql_close(mysql); mysql_close(m_mysql);
} }
} }
...@@ -184,13 +230,13 @@ DbUtil::mysqlCloseStmHandle(MYSQL_STMT *my_stmt) ...@@ -184,13 +230,13 @@ DbUtil::mysqlCloseStmHandle(MYSQL_STMT *my_stmt)
void void
DbUtil::printError(const char *msg) DbUtil::printError(const char *msg)
{ {
if (this->getMysql() && mysql_errno(this->getMysql())) if (m_mysql && mysql_errno(m_mysql))
{ {
if (this->getMysql()->server_version) if (m_mysql->server_version)
printf("\n [MySQL-%s]", this->getMysql()->server_version); printf("\n [MySQL-%s]", m_mysql->server_version);
else else
printf("\n [MySQL]"); printf("\n [MySQL]");
printf("[%d] %s\n", this->getErrorNumber(), this->getError()); printf("[%d] %s\n", getErrorNumber(), getError());
} }
else if (msg) else if (msg)
printf(" [MySQL] %s\n", msg); printf(" [MySQL] %s\n", msg);
...@@ -201,8 +247,8 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg) ...@@ -201,8 +247,8 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg)
{ {
if (stmt && mysql_stmt_errno(stmt)) if (stmt && mysql_stmt_errno(stmt))
{ {
if (this->getMysql() && this->getMysql()->server_version) if (m_mysql && m_mysql->server_version)
printf("\n [MySQL-%s]", this->getMysql()->server_version); printf("\n [MySQL-%s]", m_mysql->server_version);
else else
printf("\n [MySQL]"); printf("\n [MySQL]");
...@@ -218,16 +264,16 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg) ...@@ -218,16 +264,16 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg)
int int
DbUtil::selectDb() DbUtil::selectDb()
{ {
if ((this->getDbName()) != NULL) if ((getDbName()) != NULL)
{ {
if(mysql_select_db(this->getMysql(), this->getDbName())) if(mysql_select_db(m_mysql, this->getDbName()))
{ {
this->printError("mysql_select_db failed"); printError("mysql_select_db failed");
return DBU_FAILED; return DBU_FAILED;
} }
return DBU_OK; return DBU_OK;
} }
this->printError("getDbName() == NULL"); printError("getDbName() == NULL");
return DBU_FAILED; return DBU_FAILED;
} }
...@@ -235,9 +281,9 @@ int ...@@ -235,9 +281,9 @@ int
DbUtil::selectDb(const char * m_db) DbUtil::selectDb(const char * m_db)
{ {
{ {
if(mysql_select_db(this->getMysql(), m_db)) if(mysql_select_db(m_mysql, m_db))
{ {
this->printError("mysql_select_db failed"); printError("mysql_select_db failed");
return DBU_FAILED; return DBU_FAILED;
} }
return DBU_OK; return DBU_OK;
...@@ -249,43 +295,247 @@ DbUtil::createDb(BaseString& m_db) ...@@ -249,43 +295,247 @@ DbUtil::createDb(BaseString& m_db)
{ {
BaseString stm; BaseString stm;
{ {
if(mysql_select_db(this->getMysql(), m_db.c_str()) == DBU_OK) if(mysql_select_db(m_mysql, m_db.c_str()) == DBU_OK)
{ {
stm.assfmt("DROP DATABASE %s", m_db.c_str()); stm.assfmt("DROP DATABASE %s", m_db.c_str());
if(this->doQuery(m_db.c_str()) == DBU_FAILED) if(doQuery(m_db.c_str()) == DBU_FAILED)
return DBU_FAILED; return DBU_FAILED;
} }
stm.assfmt("CREATE DATABASE %s", m_db.c_str()); stm.assfmt("CREATE DATABASE %s", m_db.c_str());
if(this->doQuery(m_db.c_str()) == DBU_FAILED) if(doQuery(m_db.c_str()) == DBU_FAILED)
return DBU_FAILED; return DBU_FAILED;
return DBU_OK; return DBU_OK;
} }
} }
/* Run Simple Queries */
int /* Count Table Rows */
DbUtil::doQuery(BaseString& str)
unsigned long
DbUtil::selectCountTable(const char * table)
{ {
if(mysql_query(this->getMysql(), str.c_str())) BaseString query;
{ SqlResultSet result;
this->printError(str.c_str());
return DBU_FAILED; query.assfmt("select count(*) as count from %s", table);
if (!doQuery(query, result)) {
printError("select count(*) failed");
return -1;
} }
return DBU_OK; return result.columnAsInt("count");
} }
int
DbUtil::doQuery(const char * stm) /* Run Simple Queries */
{
if(mysql_query(this->getMysql(), stm))
static bool is_int_type(enum_field_types type){
switch(type){
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_ENUM:
return true;
default:
return false;
}
return false;
}
bool
DbUtil::runQuery(const char* sql,
const Properties& args,
SqlResultSet& rows){
rows.clear();
if (!isConnected())
return false;
g_debug << "runQuery: " << endl
<< " sql: '" << sql << "'" << endl;
MYSQL_STMT *stmt= mysql_stmt_init(m_mysql);
if (mysql_stmt_prepare(stmt, sql, strlen(sql)))
{ {
this->printError(stm); g_err << "Failed to prepare: " << mysql_error(m_mysql) << endl;
return DBU_FAILED; return false;
} }
return DBU_OK;
uint params= mysql_stmt_param_count(stmt);
MYSQL_BIND bind_param[params];
bzero(bind_param, sizeof(bind_param));
for(uint i= 0; i < mysql_stmt_param_count(stmt); i++)
{
BaseString name;
name.assfmt("%d", i);
// Parameters are named 0, 1, 2...
if (!args.contains(name.c_str()))
{
g_err << "param " << i << " missing" << endl;
assert(false);
}
PropertiesType t;
Uint32 val_i;
const char* val_s;
args.getTypeOf(name.c_str(), &t);
switch(t) {
case PropertiesType_Uint32:
args.get(name.c_str(), &val_i);
bind_param[i].buffer_type= MYSQL_TYPE_LONG;
bind_param[i].buffer= (char*)&val_i;
g_debug << " param" << name.c_str() << ": " << val_i << endl;
break;
case PropertiesType_char:
args.get(name.c_str(), &val_s);
bind_param[i].buffer_type= MYSQL_TYPE_STRING;
bind_param[i].buffer= (char*)val_s;
bind_param[i].buffer_length= strlen(val_s);
g_debug << " param" << name.c_str() << ": " << val_s << endl;
break;
default:
assert(false);
break;
}
}
if (mysql_stmt_bind_param(stmt, bind_param))
{
g_err << "Failed to bind param: " << mysql_error(m_mysql) << endl;
mysql_stmt_close(stmt);
return false;
}
if (mysql_stmt_execute(stmt))
{
g_err << "Failed to execute: " << mysql_error(m_mysql) << endl;
mysql_stmt_close(stmt);
return false;
}
/*
Update max_length, making it possible to know how big
buffers to allocate
*/
my_bool one= 1;
mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one);
if (mysql_stmt_store_result(stmt))
{
g_err << "Failed to store result: " << mysql_error(m_mysql) << endl;
mysql_stmt_close(stmt);
return false;
}
uint row= 0;
MYSQL_RES* res= mysql_stmt_result_metadata(stmt);
if (res != NULL)
{
MYSQL_FIELD *fields= mysql_fetch_fields(res);
uint num_fields= mysql_num_fields(res);
MYSQL_BIND bind_result[num_fields];
bzero(bind_result, sizeof(bind_result));
for (uint i= 0; i < num_fields; i++)
{
if (is_int_type(fields[i].type)){
bind_result[i].buffer_type= MYSQL_TYPE_LONG;
bind_result[i].buffer= malloc(sizeof(int));
}
else
{
uint max_length= fields[i].max_length + 1;
bind_result[i].buffer_type= MYSQL_TYPE_STRING;
bind_result[i].buffer= malloc(max_length);
bind_result[i].buffer_length= max_length;
}
}
if (mysql_stmt_bind_result(stmt, bind_result)){
g_err << "Failed to bind result: " << mysql_error(m_mysql) << endl;
mysql_stmt_close(stmt);
return false;
}
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
{
Properties curr(true);
for (uint i= 0; i < num_fields; i++){
if (is_int_type(fields[i].type))
curr.put(fields[i].name, *(int*)bind_result[i].buffer);
else
curr.put(fields[i].name, (char*)bind_result[i].buffer);
}
rows.put("row", row++, &curr);
}
mysql_free_result(res);
for (uint i= 0; i < num_fields; i++)
free(bind_result[i].buffer);
}
// Save stats in result set
rows.put("rows", row);
rows.put("affected_rows", mysql_affected_rows(m_mysql));
rows.put("mysql_errno", mysql_errno(m_mysql));
rows.put("mysql_error", mysql_error(m_mysql));
rows.put("mysql_sqlstate", mysql_sqlstate(m_mysql));
rows.put("insert_id", mysql_insert_id(m_mysql));
mysql_stmt_close(stmt);
return true;
}
bool
DbUtil::doQuery(const char* query){
const Properties args;
SqlResultSet result;
return doQuery(query, args, result);
}
bool
DbUtil::doQuery(const char* query, SqlResultSet& result){
Properties args;
return doQuery(query, args, result);
}
bool
DbUtil::doQuery(const char* query, const Properties& args,
SqlResultSet& result){
if (!runQuery(query, args, result))
return false;
result.get_row(0); // Load first row
return true;
}
bool
DbUtil::doQuery(BaseString& str){
return doQuery(str.c_str());
}
bool
DbUtil::doQuery(BaseString& str, SqlResultSet& result){
return doQuery(str.c_str(), result);
} }
bool
DbUtil::doQuery(BaseString& str, const Properties& args,
SqlResultSet& result){
return doQuery(str.c_str(), args, result);
}
/* Return MySQL Error String */ /* Return MySQL Error String */
const char * const char *
...@@ -294,7 +544,7 @@ DbUtil::getError() ...@@ -294,7 +544,7 @@ DbUtil::getError()
return mysql_error(this->getMysql()); return mysql_error(this->getMysql());
} }
/* Retrun MySQL Error Number */ /* Return MySQL Error Number */
int int
DbUtil::getErrorNumber() DbUtil::getErrorNumber()
...@@ -302,35 +552,125 @@ DbUtil::getErrorNumber() ...@@ -302,35 +552,125 @@ DbUtil::getErrorNumber()
return mysql_errno(this->getMysql()); return mysql_errno(this->getMysql());
} }
/* Count Table Rows */ /* DIE */
unsigned long void
DbUtil::selectCountTable(const char * table) DbUtil::die(const char *file, int line, const char *expr)
{ {
unsigned long m_count = 0; printf("%s:%d: check failed: '%s'\n", file, line, expr);
BaseString m_query; abort();
}
m_query.assfmt("select count(*) from %s", table);
if (mysql_query(this->getMysql(),m_query.c_str()) || /* SqlResultSet */
!(m_result=mysql_store_result(this->getMysql())))
{ bool
this->printError("selectCountTable\n"); SqlResultSet::get_row(int row_num){
return DBU_FAILED; if(!get("row", row_num, &m_curr_row)){
return false;
} }
m_row = mysql_fetch_row(m_result); return true;
m_count = (ulong) strtoull(m_row[0], (char**) 0, 10); }
mysql_free_result(m_result);
return m_count; bool
SqlResultSet::next(void){
return get_row(++m_curr_row_num);
} }
/* DIE */
void // Reset iterator
DbUtil::die(const char *file, int line, const char *expr) void SqlResultSet::reset(void){
{ m_curr_row_num= -1;
printf("%s:%d: check failed: '%s'\n", file, line, expr); m_curr_row= 0;
abort(); }
// Remove row from resultset
void SqlResultSet::remove(){
BaseString row_name;
row_name.assfmt("row_%d", m_curr_row_num);
Properties::remove(row_name.c_str());
}
SqlResultSet::SqlResultSet(): m_curr_row(0), m_curr_row_num(-1){
}
SqlResultSet::~SqlResultSet(){
}
const char* SqlResultSet::column(const char* col_name){
const char* value;
if (!m_curr_row){
g_err << "ERROR: SqlResultSet::column("<< col_name << ")" << endl
<< "There is no row loaded, call next() before "
<< "acessing the column values" << endl;
assert(m_curr_row);
}
if (!m_curr_row->get(col_name, &value))
return NULL;
return value;
}
uint SqlResultSet::columnAsInt(const char* col_name){
uint value;
if (!m_curr_row){
g_err << "ERROR: SqlResultSet::columnAsInt("<< col_name << ")" << endl
<< "There is no row loaded, call next() before "
<< "acessing the column values" << endl;
assert(m_curr_row);
}
if (!m_curr_row->get(col_name, &value))
return (uint)-1;
return value;
}
uint SqlResultSet::insertId(){
return get_int("insert_id");
}
uint SqlResultSet::affectedRows(){
return get_int("affected_rows");
}
uint SqlResultSet::numRows(void){
return get_int("rows");
}
uint SqlResultSet::mysqlErrno(void){
return get_int("mysql_errno");
}
const char* SqlResultSet::mysqlError(void){
return get_string("mysql_error");
}
const char* SqlResultSet::mysqlSqlstate(void){
return get_string("mysql_sqlstate");
}
uint SqlResultSet::get_int(const char* name){
uint value;
get(name, &value);
return value;
}
const char* SqlResultSet::get_string(const char* name){
const char* value;
get(name, &value);
return value;
} }
/* EOF */ /* EOF */
......
...@@ -23,7 +23,7 @@ libNDBT_a_SOURCES = \ ...@@ -23,7 +23,7 @@ libNDBT_a_SOURCES = \
HugoAsynchTransactions.cpp UtilTransactions.cpp \ HugoAsynchTransactions.cpp UtilTransactions.cpp \
NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \
NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c \ NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c AtrtClient.cpp \
CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp CpcClient.cpp NdbMixRestarter.cpp NDBT_Thread.cpp DbUtil.cpp
INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/storage/ndb/include/mgmcommon -I$(top_srcdir)/storage/ndb/include/kernel -I$(top_srcdir)/storage/ndb/src/mgmapi -I$(top_srcdir)/include
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment