mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
Add SqlResultSet
This commit is contained in:
parent
0d514c93d7
commit
ddf645b19c
7 changed files with 962 additions and 125 deletions
56
storage/ndb/test/include/AtrtClient.hpp
Normal file
56
storage/ndb/test/include/AtrtClient.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/* 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 @@
|
||||||
#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) \
|
||||||
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
|
||||||
{
|
{
|
||||||
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:
|
||||||
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:
|
||||||
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);};
|
||||||
|
@ -120,7 +170,7 @@ private:
|
||||||
void printError(const char *msg);
|
void printError(const char *msg);
|
||||||
void printStError(MYSQL_STMT *stmt, const char *msg);
|
void printStError(MYSQL_STMT *stmt, const char *msg);
|
||||||
void die(const char *file, int line, const char *expr); // stop program
|
void die(const char *file, int line, const char *expr); // stop program
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
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
|
||||||
|
|
173
storage/ndb/test/ndbapi/testNDBT.cpp
Normal file
173
storage/ndb/test/ndbapi/testNDBT.cpp
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
215
storage/ndb/test/src/AtrtClient.cpp
Normal file
215
storage/ndb/test/src/AtrtClient.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* 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 @@
|
||||||
/* 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 */
|
/* Constructors */
|
||||||
|
|
||||||
DbUtil::DbUtil(const char * dbname)
|
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)
|
||||||
{
|
{
|
||||||
m_port = 0;
|
|
||||||
m_connected = false;
|
|
||||||
this->setDbName(dbname);
|
|
||||||
}
|
|
||||||
|
|
||||||
DbUtil::DbUtil(const char * dbname, const char* suffix)
|
|
||||||
{
|
|
||||||
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: " << default_file.c_str() << endl;
|
ndbout << "default_file: " << m_default_file.c_str() << endl;
|
||||||
ndbout << "default_group: " << default_group.c_str() << endl;
|
ndbout << "default_group: " << m_default_group.c_str() << endl;
|
||||||
|
|
||||||
|
m_user.assign(_user);
|
||||||
|
m_pass.assign(_password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destructor*/
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DbUtil::disconnect(){
|
||||||
|
if (m_mysql != NULL){
|
||||||
|
if (m_free_mysql)
|
||||||
|
mysql_close(m_mysql);
|
||||||
|
m_mysql= NULL;
|
||||||
|
}
|
||||||
|
m_connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Destructor */
|
||||||
|
|
||||||
DbUtil::~DbUtil()
|
DbUtil::~DbUtil()
|
||||||
{
|
{
|
||||||
this->databaseLogout();
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Database Login */
|
/* Database Login */
|
||||||
|
@ -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,40 +128,40 @@ 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 */
|
||||||
|
|
||||||
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()
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -141,14 +187,14 @@ DbUtil::connect()
|
||||||
|
|
||||||
/* Database Logout */
|
/* Database Logout */
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,28 +227,28 @@ DbUtil::mysqlCloseStmHandle(MYSQL_STMT *my_stmt)
|
||||||
|
|
||||||
/* Error Printing */
|
/* Error Printing */
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DbUtil::printStError(MYSQL_STMT *stmt, const char *msg)
|
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]");
|
||||||
|
|
||||||
|
@ -215,19 +261,19 @@ DbUtil::printStError(MYSQL_STMT *stmt, const char *msg)
|
||||||
|
|
||||||
/* Select which database to use */
|
/* Select which database to use */
|
||||||
|
|
||||||
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
|
||||||
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,89 +295,383 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Count Table Rows */
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
DbUtil::selectCountTable(const char * table)
|
||||||
|
{
|
||||||
|
BaseString query;
|
||||||
|
SqlResultSet result;
|
||||||
|
|
||||||
|
query.assfmt("select count(*) as count from %s", table);
|
||||||
|
if (!doQuery(query, result)) {
|
||||||
|
printError("select count(*) failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return result.columnAsInt("count");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Run Simple Queries */
|
/* Run Simple Queries */
|
||||||
|
|
||||||
int
|
|
||||||
DbUtil::doQuery(BaseString& str)
|
static bool is_int_type(enum_field_types type){
|
||||||
{
|
switch(type){
|
||||||
if(mysql_query(this->getMysql(), str.c_str()))
|
case MYSQL_TYPE_TINY:
|
||||||
{
|
case MYSQL_TYPE_SHORT:
|
||||||
this->printError(str.c_str());
|
case MYSQL_TYPE_LONGLONG:
|
||||||
return DBU_FAILED;
|
case MYSQL_TYPE_INT24:
|
||||||
|
case MYSQL_TYPE_LONG:
|
||||||
|
case MYSQL_TYPE_ENUM:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return DBU_OK;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
DbUtil::doQuery(const char * stm)
|
bool
|
||||||
{
|
DbUtil::runQuery(const char* sql,
|
||||||
if(mysql_query(this->getMysql(), stm))
|
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 *
|
||||||
DbUtil::getError()
|
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()
|
||||||
{
|
{
|
||||||
return mysql_errno(this->getMysql());
|
return mysql_errno(this->getMysql());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count Table Rows */
|
|
||||||
|
|
||||||
unsigned long
|
|
||||||
DbUtil::selectCountTable(const char * table)
|
|
||||||
{
|
|
||||||
unsigned long m_count = 0;
|
|
||||||
BaseString m_query;
|
|
||||||
|
|
||||||
m_query.assfmt("select count(*) from %s", table);
|
|
||||||
if (mysql_query(this->getMysql(),m_query.c_str()) ||
|
|
||||||
!(m_result=mysql_store_result(this->getMysql())))
|
|
||||||
{
|
|
||||||
this->printError("selectCountTable\n");
|
|
||||||
return DBU_FAILED;
|
|
||||||
}
|
|
||||||
m_row = mysql_fetch_row(m_result);
|
|
||||||
m_count = (ulong) strtoull(m_row[0], (char**) 0, 10);
|
|
||||||
mysql_free_result(m_result);
|
|
||||||
|
|
||||||
return m_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DIE */
|
/* DIE */
|
||||||
|
|
||||||
void
|
void
|
||||||
DbUtil::die(const char *file, int line, const char *expr)
|
DbUtil::die(const char *file, int line, const char *expr)
|
||||||
{
|
{
|
||||||
printf("%s:%d: check failed: '%s'\n", file, line, expr);
|
printf("%s:%d: check failed: '%s'\n", file, line, expr);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SqlResultSet */
|
||||||
|
|
||||||
|
bool
|
||||||
|
SqlResultSet::get_row(int row_num){
|
||||||
|
if(!get("row", row_num, &m_curr_row)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
SqlResultSet::next(void){
|
||||||
|
return get_row(++m_curr_row_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset iterator
|
||||||
|
void SqlResultSet::reset(void){
|
||||||
|
m_curr_row_num= -1;
|
||||||
|
m_curr_row= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 = \
|
||||||
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
|
||||||
|
|
Loading…
Add table
Reference in a new issue