Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duckdb #45

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ CMakeFiles
Makefile
*.a
src/pstress-*
.vscode/*
38 changes: 31 additions & 7 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
IF (MYSQL_FOUND)
SET (BINARY_NAME "pstress")
ADD_SUBDIRECTORY(third_party)
INCLUDE_DIRECTORIES(third_party/inih++/include third_party/rapidjson/include)
option(USE_DUCKDB "Enable support for DuckDB" OFF)
option(USE_MYSQL "Enable support for MySQL" ON)
SET(BINARY_NAME "pstress")
ADD_SUBDIRECTORY(third_party)
INCLUDE_DIRECTORIES(third_party/inih++/include third_party/rapidjson/include)

IF (USE_MYSQL AND MYSQL_FOUND)
MESSAGE(STATUS "Configuring for MySQL...")
IF (MARIADB)
INCLUDE_DIRECTORIES( ${MYSQL_INCLUDE_DIR} ${MYSQL_INCLUDE_DIR}/.. )
ELSE()
INCLUDE_DIRECTORIES( ${MYSQL_INCLUDE_DIR} )
ENDIF(MARIADB)
ADD_EXECUTABLE(${BINARY_NAME}-${PSTRESS_EXT} pstress.cpp help.cpp node.cpp thread.cpp random_test.cpp)
TARGET_LINK_LIBRARIES( ${BINARY_NAME}-${PSTRESS_EXT} ${MYSQL_LIBRARY} ${OTHER_LIBS} inih++)
FILE(COPY
INSTALL(TARGETS ${BINARY_NAME}-${PSTRESS_EXT} DESTINATION bin)
ENDIF(USE_MYSQL AND MYSQL_FOUND)

IF (USE_DUCKDB)
MESSAGE(STATUS "Configuring for DuckDB...")

# Manually set the paths for DuckDB if not found
set(DUCKDB_INCLUDE_DIR "/usr/local/lib")
set(DUCKDB_LIBRARY "/usr/local/lib/libduckdb.so")

# Check if DuckDB includes and libraries are provided
if (DUCKDB_INCLUDE_DIR AND DUCKDB_LIBRARY)
INCLUDE_DIRECTORIES(${DUCKDB_INCLUDE_DIR})
ADD_EXECUTABLE(${BINARY_NAME}-duckdb pstress.cpp help.cpp node.cpp thread.cpp random_test.cpp)
TARGET_LINK_LIBRARIES(${BINARY_NAME}-duckdb ${DUCKDB_LIBRARY} ${OTHER_LIBS} inih++)
INSTALL(TARGETS ${BINARY_NAME}-duckdb DESTINATION bin)
else()
message(FATAL_ERROR "DuckDB include or library not found")
endif()

ENDIF(USE_DUCKDB)

FILE(COPY
grammar.sql
DESTINATION .)
INSTALL(FILES grammar.sql DESTINATION bin)
INSTALL(TARGETS ${BINARY_NAME}-${PSTRESS_EXT} DESTINATION bin)
ENDIF(MYSQL_FOUND)
SET( CMAKE_EXPORT_COMPILE_COMMANDS ON )
2 changes: 2 additions & 0 deletions src/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ struct Option {
DELETE_ALL_ROW,
DELETE_ROW_USING_PKEY,
INVALID_OPTION = 63,
DUCKDB,
LOG_ALL_QUERIES = 'A',
LOG_N_QUERIES,
PQUERY = 'k',
DATABASE = 'd',
ADDRESS = 'a',
Expand Down
16 changes: 16 additions & 0 deletions src/help.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,18 @@ void add_options() {
opt->setBool(false);
opt->setArgs(no_argument);

/* log recent N queries */
opt = newOption(Option::INT, Option::LOG_N_QUERIES, "log-N-queries");
opt->help = "Set the number of queries to log (default is 5)";
opt->setInt(5);
opt->setArgs(required_argument);

/* Use DuckDb */
opt = newOption(Option::BOOL, Option::DUCKDB, "duckdb");
opt->help = "Use DuckDB as database backend";
opt->setBool(false);
opt->setArgs(no_argument);

/* execute sql sequentially */
opt = newOption(Option::BOOL, Option::NO_SHUFFLE, "no-shuffle");
opt->help = "execute SQL sequentially | randomly\n";
Expand Down Expand Up @@ -1259,6 +1271,8 @@ void show_cli_help(void) {
"threads=1 | no\n"
<< "--log-all-queries | Log all queries (succeeded and "
"failed) | no\n"
<< "--log-N-queries | Log recent N queries (succeeded and "
"failed) | 5\n"
<< "--log-succeeded-queries| Log succeeded queries "
" | no\n"
<< "--log-failed-queries | Log failed queries "
Expand Down Expand Up @@ -1316,6 +1330,8 @@ void show_config_help(void) {
"verbose = No\n"
<< "# Log all queries\n"
<< "log-all-queries = No\n"
<< "# Log recent N queries\n"
<< "log-N-queries = 5\n"
<< "# Log succeeded queries\n"
<< "log-succeeded-queries = No\n"
<< "# Log failed queries\n"
Expand Down
136 changes: 82 additions & 54 deletions src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ bool Node::createGeneralLog() {
}
general_log.open(logName, std::ios::out | std::ios::trunc);
general_log << "- PStress v" << PQVERSION << "-" << PQREVISION
<< " compiled with " << FORK << "-" << mysql_get_client_info()
<< std::endl;
<< " compiled with " << FORK;
#ifdef USE_MYSQL
general_log << "-" << mysql_get_client_info();
#endif

#ifdef USE_DUCKDB
general_log << "-" << duckdb::LibraryVersion();
#endif

general_log << std::endl;

if (!general_log.is_open()) {
std::cout << "Unable to open log file " << logName << ": "
Expand Down Expand Up @@ -128,62 +136,82 @@ int Node::startWork() {

void Node::tryConnect() {
node_mutex.lock();
MYSQL *conn;
conn = mysql_init(NULL);
if (conn == NULL) {
std::cerr << "Error " << mysql_errno(conn) << ": " << mysql_error(conn)
<< std::endl;
std::cerr << "* PSTRESS: Unable to continue [1], exiting" << std::endl;
general_log << "Error " << mysql_errno(conn) << ": " << mysql_error(conn)
<< std::endl;
general_log << "* PSTRESS: Unable to continue [1], exiting" << std::endl;
mysql_close(conn);
mysql_library_end();
exit(EXIT_FAILURE);
}
if (mysql_real_connect(conn, myParams.address.c_str(),
myParams.username.c_str(), myParams.password.c_str(),
options->at(Option::DATABASE)->getString().c_str(),
myParams.port, myParams.socket.c_str(), 0) == NULL) {
std::cerr << "Error " << mysql_errno(conn) << ": " << mysql_error(conn)
<< std::endl;
std::cerr << "* PSTRESS: Unable to continue [2], exiting" << std::endl;
general_log << "Error " << mysql_errno(conn) << ": " << mysql_error(conn)
<< std::endl;
general_log << "* PSTRESS: Unable to continue [2], exiting" << std::endl;
mysql_close(conn);
mysql_library_end();
exit(EXIT_FAILURE);
}
general_log << "- Connected to " << mysql_get_host_info(conn) << "..."
<< std::endl;
// getting the real server version
MYSQL_RES *result = NULL;
std::string server_version;

if (!mysql_query(conn, "select @@version_comment limit 1") &&
(result = mysql_use_result(conn))) {
MYSQL_ROW row = mysql_fetch_row(result);
if (row && row[0]) {
#ifdef MYSQL
MYSQL *conn = mysql_init(NULL);
if (conn == NULL) {
std::cerr << "Error: Unable to initialize MySQL connection." << std::endl;
general_log << "Error: Unable to initialize MySQL connection." << std::endl;
exit(EXIT_FAILURE);
}

if (mysql_real_connect(conn, myParams.address.c_str(),
myParams.username.c_str(), myParams.password.c_str(),
options->at(Option::DATABASE)->getString().c_str(),
myParams.port, myParams.socket.c_str(), 0) == NULL) {
std::cerr << "MySQL Error " << mysql_errno(conn) << ": " << mysql_error(conn) << std::endl;
general_log << "MySQL Error " << mysql_errno(conn) << ": " << mysql_error(conn) << std::endl;
mysql_close(conn);
mysql_library_end();
exit(EXIT_FAILURE);
}

general_log << "- Connected to MySQL: " << mysql_get_host_info(conn) << std::endl;

// Get MySQL server version
MYSQL_RES *result = NULL;
std::string server_version;
if (!mysql_query(conn, "SELECT @@version_comment LIMIT 1") &&
(result = mysql_use_result(conn))) {
MYSQL_ROW row = mysql_fetch_row(result);
if (row && row[0]) {
server_version = mysql_get_server_info(conn);
server_version.append(" ");
server_version.append(row[0]);
}
} else {
server_version = mysql_get_server_info(conn);
server_version.append(" ");
server_version.append(row[0]);
}
} else {
server_version = mysql_get_server_info(conn);
}
general_log << "- Connected server version: " << server_version << std::endl;
if (strcmp(PLATFORM_ID, "Darwin") == 0)
general_log << "- Table compression is disabled as hole punching is not "
"supported on OSX"
<< std::endl;
if (result != NULL) {
mysql_free_result(result);
}
mysql_close(conn);
mysql_thread_end();
general_log << "- MySQL server version: " << server_version << std::endl;

if (result != NULL) {
mysql_free_result(result);
}
mysql_close(conn);
mysql_thread_end();

#elif defined(DUCKDB)
duckdb_database db;
duckdb_connection conn;
if (duckdb_open(myParams.database_path.c_str(), &db) != DuckDBSuccess) {
std::cerr << "Error: Unable to open DuckDB database." << std::endl;
general_log << "Error: Unable to open DuckDB database." << std::endl;
exit(EXIT_FAILURE);
}

if (duckdb_connect(db, &conn) != DuckDBSuccess) {
std::cerr << "Error: Unable to connect to DuckDB." << std::endl;
general_log << "Error: Unable to connect to DuckDB." << std::endl;
duckdb_close(&db);
exit(EXIT_FAILURE);
}

general_log << "- Connected to DuckDB." << std::endl;

// Get DuckDB version
general_log << "- DuckDB version: " << duckdb_library_version() << std::endl;

duckdb_disconnect(&conn);
duckdb_close(&db);

#else
std::cerr << "Error: No database backend defined." << std::endl;
general_log << "Error: No database backend defined." << std::endl;
exit(EXIT_FAILURE);
#endif

if (options->at(Option::TEST_CONNECTION)->getBool()) {
exit(EXIT_SUCCESS);
}

node_mutex.unlock();
}
17 changes: 16 additions & 1 deletion src/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
#include <atomic>
#include <fstream>
#include <iostream>
#ifdef USE_MYSQL
#include <mysql.h>
#endif

#ifdef USE_DUCKDB
#include "duckdb.hpp"
#endif
#include <sstream>
#include <string>
#include <sys/stat.h>
Expand Down Expand Up @@ -51,6 +57,7 @@ enum LogLevel {
LOG_FAILED_QUERIES = 1 << 4,
LOG_SUCCEDED_QUERIES = 1 << 5,
LOG_ALL_QUERIES = LOG_FAILED_QUERIES | LOG_SUCCEDED_QUERIES,
LOG_N_QUERIES = 1 << 6, // New log enum
LOG_CURRENT = LOG_NOTHING
};

Expand All @@ -68,8 +75,16 @@ class Node {
private:
// declaration for worker thread function
void workerThread(int);
inline unsigned long long getAffectedRows(MYSQL *);
void tryConnect();
#ifdef USE_MYSQL
inline unsigned long long getAffectedRows(MYSQL *);
void tryConnect(); // MySQL-specific connection logic
#endif

#ifdef USE_DUCKDB
inline unsigned long long getAffectedRows(duckdb::Connection *);
void tryConnect(); // DuckDB-specific connection logic
#endif
bool createGeneralLog();
void readSettings(std::string);
void writeFinalReport();
Expand Down
10 changes: 9 additions & 1 deletion src/pstress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
#include "random_test.hpp"
#include <INIReader.hpp>
#include <libgen.h> //dirname() uses this
#ifdef USE_MYSQL
#include <mysql.h>
#endif

#ifdef USE_DUCKDB
#include "duckdb.hpp"
#endif
#include <string>
#include <thread>

Expand Down Expand Up @@ -197,7 +203,9 @@ int main(int argc, char *argv[]) {

save_metadata_to_file();
clean_up_at_end();
mysql_library_end();
#ifdef USE_MYSQL
mysql_library_end();
#endif
delete_options();
std::cout << "COMPLETED" << std::endl;
if (run_query_failed)
Expand Down
Loading