SQL API refactoring, cut #1.

This commit is contained in:
Alexey Kopytov
2017-01-11 19:31:37 +03:00
parent 278a14fd9f
commit 1d434809ec
66 changed files with 2701 additions and 1364 deletions

1
.gitignore vendored
View File

@ -74,3 +74,4 @@ third_party/luajit/lib/
third_party/luajit/share/
third_party/luajit/tmp/
sysbench/lua/internal/sysbench.lua.h
sysbench/lua/internal/sysbench.sql.lua.h

View File

@ -306,6 +306,10 @@ AX_TLS([],
# __attribute__((format...)) function attribute
AX_GCC_FUNC_ATTRIBUTE(format)
# Define HAVE_FUNC_ATTRIBUTE_UNUSED if compiler supports the
# __attribute__((unused)) function attribute
AX_GCC_FUNC_ATTRIBUTE(unused)
if test "$enable_largefile" = yes; then
AC_SYS_LARGEFILE
fi

View File

@ -47,8 +47,9 @@ endif
sysbench_SOURCES = sysbench.c sysbench.h sb_timer.c sb_timer.h \
sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \
db_driver.c sb_histogram.c sb_histogram.h sb_rand.c sb_rand.h \
sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_global.h sb_lua.c \
sb_lua.h lua/internal/sysbench.lua.h sb_util.h xoroshiro128plus.h
sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_lua.c \
sb_lua.h lua/internal/sysbench.lua.h lua/internal/sysbench.sql.lua.h sb_util.h \
xoroshiro128plus.h
sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \
tests/memory/libsbmemory.a tests/cpu/libsbcpu.a \

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2004 MySQL AB
Copyright (C) 2004-2016 Alexey Kopytov <akopytov@gmail.com>
Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
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
@ -26,7 +26,8 @@
#include "sysbench.h"
#include "sb_list.h"
#include "sb_histogram.h"
#include "sb_util.h"
#include "ck_pr.h"
/* Prepared statements usage modes */
@ -45,8 +46,6 @@ typedef struct
unsigned char debug; /* debug flag */
} db_globals_t;
extern db_globals_t db_globals;
/* Driver capabilities definition */
typedef struct
@ -63,10 +62,10 @@ typedef struct
typedef enum
{
SB_DB_ERROR_NONE,
SB_DB_ERROR_RESTART_TRANSACTION,
SB_DB_ERROR_RECONNECTED,
SB_DB_ERROR_FAILED
DB_ERROR_NONE, /* no error(s) */
DB_ERROR_IGNORABLE, /* error should be ignored as defined by command
line arguments or a custom error handler */
DB_ERROR_FATAL /* non-ignorable error */
} db_error_t;
@ -118,32 +117,33 @@ typedef struct
struct db_conn;
struct db_stmt;
struct db_result_set;
struct db_result;
struct db_row;
/* Driver operations definition */
typedef int drv_op_init(void);
typedef int drv_op_thread_init(int);
typedef int drv_op_describe(drv_caps_t *);
typedef int drv_op_connect(struct db_conn *);
typedef int drv_op_disconnect(struct db_conn *);
typedef int drv_op_prepare(struct db_stmt *, const char *);
typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, unsigned int);
typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, unsigned int );
typedef int drv_op_execute(struct db_stmt *, struct db_result_set *);
typedef int drv_op_fetch(struct db_result_set *);
typedef int drv_op_fetch_row(struct db_result_set *, struct db_row *);
typedef unsigned long long drv_op_num_rows(struct db_result_set *);
typedef int drv_op_query(struct db_conn *, const char *,
struct db_result_set *);
typedef int drv_op_free_results(struct db_result_set *);
typedef int drv_op_prepare(struct db_stmt *, const char *, size_t);
typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, size_t);
typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, size_t);
typedef db_error_t drv_op_execute(struct db_stmt *, struct db_result *);
typedef int drv_op_fetch(struct db_result *);
typedef int drv_op_fetch_row(struct db_result *, struct db_row *);
typedef db_error_t drv_op_query(struct db_conn *, const char *, size_t,
struct db_result *);
typedef int drv_op_free_results(struct db_result *);
typedef int drv_op_close(struct db_stmt *);
typedef int drv_op_store_results(struct db_result_set *);
typedef int drv_op_thread_done(int);
typedef int drv_op_done(void);
typedef struct
{
drv_op_init *init; /* initializate driver */
drv_op_thread_init *thread_init; /* thread-local driver initialization */
drv_op_describe *describe; /* describe database capabilities */
drv_op_connect *connect; /* connect to database */
drv_op_disconnect *disconnect; /* disconnect from database */
@ -153,11 +153,10 @@ typedef struct
drv_op_execute *execute; /* execute prepared statement */
drv_op_fetch *fetch; /* fetch row for prepared statement */
drv_op_fetch_row *fetch_row; /* fetch row for queries */
drv_op_num_rows *num_rows; /* return number of rows in result set */
drv_op_free_results *free_results; /* free result set */
drv_op_close *close; /* close prepared statement */
drv_op_query *query; /* execute non-prepared statement */
drv_op_store_results *store_results; /* store results from last query */
drv_op_thread_done *thread_done; /* thread-local driver deinitialization */
drv_op_done *done; /* uninitialize driver */
} drv_ops_t;
@ -171,55 +170,65 @@ typedef struct
drv_ops_t ops; /* driver operations */
sb_list_item_t listitem; /* can be linked in a list */
bool initialized;
pthread_mutex_t mutex;
} db_driver_t;
/* Connection types definition */
/* Query type for statistics */
typedef enum {
DB_CONN_TYPE_UNUSED,
DB_CONN_TYPE_MYSQL
} db_conn_type_t;
DB_STAT_OTHER,
DB_STAT_READ,
DB_STAT_WRITE,
DB_STAT_TRX,
DB_STAT_ERROR,
DB_STAT_RECONNECT,
DB_STAT_MAX
} db_stat_type_t;
/* Result set definition */
typedef struct db_result_set
typedef struct db_result
{
struct db_conn *connection; /* Connection which this result set belongs to */
struct db_stmt *statement; /* Statement for this result set (if any) */
db_stat_type_t stat_type; /* Statistical counter type */
uint32_t nrows; /* Number of affected rows */
struct db_stmt *statement; /* Pointer to prepared statement (if used) */
void *ptr; /* Pointer to driver-specific data */
} db_result_t;
struct db_row *row; /* Last row fetched by db_fetch_row */
void *ptr; /* Pointer to driver-specific data */
unsigned long long nrows; /* Number of rows in a result set */
} db_result_set_t;
typedef enum {
DB_CONN_READY,
DB_CONN_RESULT_SET,
DB_CONN_INVALID
} db_conn_state_t;
/* Database connection structure */
typedef struct db_conn
{
db_driver_t *driver; /* DB driver for this connection */
db_conn_type_t type;
void *ptr;
db_error_t db_errno;
db_driver_t *driver; /* DB driver for this connection */
void *ptr; /* Driver-specific data */
db_error_t db_errno; /* Driver-independent error code */
db_conn_state_t state; /* Connection state */
db_result_t rs; /* Result set */
int thread_id; /* Assiciated thread id (required to
collect per-thread stats */
/* Internal fields */
char bulk_supported; /* 1, if multi-row inserts are supported by the driver */
char bulk_supported; /* 1, if multi-row inserts are supported by
the driver */
unsigned int bulk_cnt; /* Current number of rows in bulk insert buffer */
char * bulk_buffer; /* Bulk insert query buffer */
unsigned int bulk_buflen; /* Current length of bulk_buffer */
char *bulk_buffer; /* Bulk insert query buffer */
unsigned int bulk_ptr; /* Current position in bulk_buffer */
unsigned int bulk_ptr_orig; /* Save value of bulk_ptr */
unsigned int bulk_values; /* Save value of bulk_ptr */
unsigned int bulk_commit_cnt; /* Current value of uncommitted rows */
unsigned int bulk_commit_max; /* Maximum value of uncommitted rows */
int thread_id; /* Assiciated thread id (required to collect per-thread stats */
db_result_set_t rs; /* Result set */
} db_conn_t;
typedef enum {
DB_QUERY_TYPE_READ,
DB_QUERY_TYPE_WRITE,
DB_QUERY_TYPE_COMMIT,
DB_QUERY_TYPE_OTHER
} db_query_type_t;
char pad[SB_CACHELINE_PAD(sizeof(void *) * 3 + sizeof(db_error_t) +
sizeof(db_conn_state_t) +
sizeof(db_result_t) +
sizeof(int) * 8)];
} db_conn_t;
/* Prepared statement definition */
@ -232,7 +241,7 @@ typedef struct db_stmt
db_bind_t *bound_res; /* Array of bound results for emulated PS */
db_bind_t *bound_res_len; /* Length of the bound_res array */
char emulated; /* Should this statement be emulated? */
db_query_type_t type; /* Query type */
db_stat_type_t stat_type; /* Query type */
void *ptr; /* Pointer to driver-specific data structure */
} db_stmt_t;
@ -240,58 +249,69 @@ typedef struct db_stmt
typedef struct db_row
{
db_result_set_t *result_set; /* Result set which this row belongs to */
db_result_t *result; /* Result set which this row belongs to */
void *ptr; /* Driver-specific row data */
} db_row_t;
/*
sizeof(db_stats_t) must be multiple of CK_MD_CACHELINE to avoid cache
line sharing.
*/
typedef uint64_t
db_stats_t[SB_ALIGN(DB_STAT_MAX * sizeof(uint64_t), CK_MD_CACHELINE) /
sizeof(uint64_t)];
extern db_globals_t db_globals;
extern db_stats_t *thread_stats;
/* Database abstraction layer calls */
int db_register(void);
void db_print_help(void);
db_driver_t *db_init(const char *);
db_driver_t *db_create(const char *);
int db_destroy(db_driver_t *);
int db_describe(db_driver_t *, drv_caps_t *);
db_conn_t *db_connect(db_driver_t *);
db_conn_t *db_connection_create(db_driver_t *);
int db_disconnect(db_conn_t *);
int db_connection_close(db_conn_t *);
db_stmt_t *db_prepare(db_conn_t *, const char *);
void db_connection_free(db_conn_t *con);
int db_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
db_stmt_t *db_prepare(db_conn_t *, const char *, size_t);
int db_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
int db_bind_param(db_stmt_t *, db_bind_t *, size_t);
db_result_set_t *db_execute(db_stmt_t *);
int db_bind_result(db_stmt_t *, db_bind_t *, size_t);
db_row_t *db_fetch_row(db_result_set_t *);
db_result_t *db_execute(db_stmt_t *);
unsigned long long db_num_rows(db_result_set_t *);
db_row_t *db_fetch_row(db_result_t *);
db_result_set_t *db_query(db_conn_t *, const char *);
db_result_t *db_query(db_conn_t *, const char *, size_t len);
int db_free_results(db_result_set_t *);
int db_free_results(db_result_t *);
int db_store_results(db_result_set_t *);
int db_store_results(db_result_t *);
int db_close(db_stmt_t *);
int db_done(db_driver_t *);
db_error_t db_errno(db_conn_t *);
void db_done(void);
int db_print_value(db_bind_t *, char *, int);
/* Initialize multi-row insert operation */
int db_bulk_insert_init(db_conn_t *, const char *);
int db_bulk_insert_init(db_conn_t *, const char *, size_t);
/* Add row to multi-row insert operation */
int db_bulk_insert_next(db_conn_t *, const char *);
int db_bulk_insert_next(db_conn_t *, const char *, size_t);
/* Finish multi-row insert operation */
void db_bulk_insert_done(db_conn_t *);
int db_bulk_insert_done(db_conn_t *);
/* Print database-specific test stats */
void db_print_stats(sb_stat_t type);
@ -299,6 +319,16 @@ void db_print_stats(sb_stat_t type);
/* Associate connection with a thread (required only for statistics */
void db_set_thread(db_conn_t *, int);
/* Initialize per-thread stats */
int db_thread_stat_init(void);
/* Increment a given stat counter for a connection */
static inline void db_thread_stat_inc(int id, db_stat_type_t type)
{
ck_pr_inc_64(&thread_stats[id][type]);
}
/* DB drivers registrars */
#ifdef USE_MYSQL

View File

@ -86,17 +86,17 @@ static int attachsql_drv_init(void);
static int attachsql_drv_describe(drv_caps_t *);
static int attachsql_drv_connect(db_conn_t *);
static int attachsql_drv_disconnect(db_conn_t *);
static int attachsql_drv_prepare(db_stmt_t *, const char *);
static int attachsql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
static int attachsql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
static int attachsql_drv_execute(db_stmt_t *, db_result_set_t *);
static int attachsql_drv_fetch(db_result_set_t *);
static int attachsql_drv_fetch_row(db_result_set_t *, db_row_t *);
static unsigned long long attachsql_drv_num_rows(db_result_set_t *);
static int attachsql_drv_query(db_conn_t *, const char *, db_result_set_t *);
static int attachsql_drv_free_results(db_result_set_t *);
static int attachsql_drv_prepare(db_stmt_t *, const char *, size_t);
static int attachsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
static int attachsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
static db_error_t attachsql_drv_execute(db_stmt_t *, db_result_t *);
static int attachsql_drv_fetch(db_result_t *);
static int attachsql_drv_fetch_row(db_result_t *, db_row_t *);
static db_error_t attachsql_drv_query(db_conn_t *, const char *, size_t,
db_result_t *);
static int attachsql_drv_free_results(db_result_t *);
static int attachsql_drv_close(db_stmt_t *);
static int attachsql_drv_store_results(db_result_set_t *);
static int attachsql_drv_store_results(db_result_t *);
static int attachsql_drv_done(void);
/* libAttachSQL driver definition */
@ -108,24 +108,22 @@ static db_driver_t attachsql_driver =
.args = attachsql_drv_args,
.ops =
{
attachsql_drv_init,
attachsql_drv_describe,
attachsql_drv_connect,
attachsql_drv_disconnect,
attachsql_drv_prepare,
attachsql_drv_bind_param,
attachsql_drv_bind_result,
attachsql_drv_execute,
attachsql_drv_fetch,
attachsql_drv_fetch_row,
attachsql_drv_num_rows,
attachsql_drv_free_results,
attachsql_drv_close,
attachsql_drv_query,
attachsql_drv_store_results,
attachsql_drv_done
},
.listitem = {NULL, NULL}
.init = attachsql_drv_init,
.describe = attachsql_drv_describe,
.connect = attachsql_drv_connect,
.disconnect = attachsql_drv_disconnect,
.prepare = attachsql_drv_prepare,
.bind_param = attachsql_drv_bind_param,
.bind_result = attachsql_drv_bind_result,
.execute = attachsql_drv_execute,
.fetch = attachsql_drv_fetch,
.fetch_row = attachsql_drv_fetch_row,
.free_results = attachsql_drv_free_results,
.close = attachsql_drv_close,
.query = attachsql_drv_query,
.store_results = attachsql_drv_store_results,
.done = attachsql_drv_done
}
};
@ -280,12 +278,12 @@ int attachsql_drv_disconnect(db_conn_t *sb_conn)
/* Prepare statement */
int attachsql_drv_prepare(db_stmt_t *stmt, const char *query)
int attachsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
{
attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr;
attachsql_error_t *error= NULL;
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
attachsql_statement_prepare(con, strlen(query), query, &error);
attachsql_statement_prepare(con, len, query, &error);
while(aret != ATTACHSQL_RETURN_EOF)
{
aret= attachsql_connect_poll(con, &error);
@ -302,7 +300,7 @@ int attachsql_drv_prepare(db_stmt_t *stmt, const char *query)
/* Bind parameters for prepared statement */
int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
/* libAttachSQL doesn't do this, you do this during execute
* this is because sysbench doesn't set the values until that time
@ -322,7 +320,7 @@ int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int le
/* Bind results for prepared statement */
int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
(void)stmt;
(void)params;
@ -335,7 +333,7 @@ int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int l
/* Execute prepared statement */
int attachsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
db_error_t attachsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
{
(void) rs;
attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr;
@ -426,8 +424,8 @@ int attachsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
/* Execute SQL query */
int attachsql_drv_query(db_conn_t *sb_conn, const char *query,
db_result_set_t *rs)
db_error_t attachsql_drv_query(db_conn_t *sb_conn, const char *query,
size_t len, db_result_t *rs)
{
(void) rs;
attachsql_connect_t *con = sb_conn->ptr;
@ -441,8 +439,8 @@ int attachsql_drv_query(db_conn_t *sb_conn, const char *query,
DEBUG("attachsql_query(%p, \"%s\", %u)",
con,
query,
strlen(query));
attachsql_query(con, strlen(query), query, 0, NULL, &error);
len);
attachsql_query(con, len, query, 0, NULL, &error);
while((aret != ATTACHSQL_RETURN_EOF) && (aret != ATTACHSQL_RETURN_ROW_READY))
{
@ -471,7 +469,7 @@ int attachsql_drv_query(db_conn_t *sb_conn, const char *query,
/* Fetch row from result set of a prepared statement */
int attachsql_drv_fetch(db_result_set_t *rs)
int attachsql_drv_fetch(db_result_t *rs)
{
/* NYI */
attachsql_connect_t *con = rs->connection->ptr;
@ -531,7 +529,7 @@ int attachsql_drv_fetch(db_result_set_t *rs)
/* Fetch row from result set of a query */
int attachsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
int attachsql_drv_fetch_row(db_result_t *rs, db_row_t *row)
{
attachsql_error_t *error= NULL;
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
@ -562,19 +560,10 @@ int attachsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
}
/* Return the number of rows in a result set */
unsigned long long attachsql_drv_num_rows(db_result_set_t *rs)
{
return rs->nrows;
}
/* Store results from the last query */
int attachsql_drv_store_results(db_result_set_t *rs)
int attachsql_drv_store_results(db_result_t *rs)
{
int ret= 0;
db_row_t row;
@ -598,13 +587,14 @@ int attachsql_drv_store_results(db_result_set_t *rs)
/* Free result set */
int attachsql_drv_free_results(db_result_set_t *rs)
int attachsql_drv_free_results(db_result_t *rs)
{
if (rs->connection->ptr != NULL)
{
DEBUG("attachsql_query_close(%p)", rs->connection->ptr);
attachsql_query_close(rs->connection->ptr);
rs->connection->ptr = NULL;
return 0;
}

View File

@ -96,17 +96,17 @@ static int drizzle_drv_init(void);
static int drizzle_drv_describe(drv_caps_t *);
static int drizzle_drv_connect(db_conn_t *);
static int drizzle_drv_disconnect(db_conn_t *);
static int drizzle_drv_prepare(db_stmt_t *, const char *);
static int drizzle_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
static int drizzle_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
static int drizzle_drv_execute(db_stmt_t *, db_result_set_t *);
static int drizzle_drv_fetch(db_result_set_t *);
static int drizzle_drv_fetch_row(db_result_set_t *, db_row_t *);
static unsigned long long drizzle_drv_num_rows(db_result_set_t *);
static int drizzle_drv_query(db_conn_t *, const char *, db_result_set_t *);
static int drizzle_drv_free_results(db_result_set_t *);
static int drizzle_drv_prepare(db_stmt_t *, const char *, size_t);
static int drizzle_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
static int drizzle_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
static db_error_t drizzle_drv_execute(db_stmt_t *, db_result_t *);
static int drizzle_drv_fetch(db_result_t *);
static int drizzle_drv_fetch_row(db_result_t *, db_row_t *);
static db_error_t drizzle_drv_query(db_conn_t *, const char *, size_t,
db_result_t *);
static int drizzle_drv_free_results(db_result_t *);
static int drizzle_drv_close(db_stmt_t *);
static int drizzle_drv_store_results(db_result_set_t *);
static int drizzle_drv_store_results(db_result_t *);
static int drizzle_drv_done(void);
/* Drizzle driver definition */
@ -118,24 +118,22 @@ static db_driver_t drizzle_driver =
.args = drizzle_drv_args,
.ops =
{
drizzle_drv_init,
drizzle_drv_describe,
drizzle_drv_connect,
drizzle_drv_disconnect,
drizzle_drv_prepare,
drizzle_drv_bind_param,
drizzle_drv_bind_result,
drizzle_drv_execute,
drizzle_drv_fetch,
drizzle_drv_fetch_row,
drizzle_drv_num_rows,
drizzle_drv_free_results,
drizzle_drv_close,
drizzle_drv_query,
drizzle_drv_store_results,
drizzle_drv_done
.init = drizzle_drv_init,
.describe = drizzle_drv_describe,
.connect = drizzle_drv_connect,
.disconnect = drizzle_drv_disconnect,
.prepare = drizzle_drv_prepare,
.bind_param = drizzle_drv_bind_param,
.bind_result = drizzle_drv_bind_result,
.execute = drizzle_drv_execute,
.fetch = drizzle_drv_fetch,
.fetch_row = drizzle_drv_fetch_row,
.free_results = drizzle_drv_free_results,
.close = drizzle_drv_close,
.query = drizzle_drv_query,
.store_results = drizzle_drv_store_results,
.done = drizzle_drv_done
},
.listitem = {NULL, NULL}
};
@ -299,9 +297,11 @@ int drizzle_drv_disconnect(db_conn_t *sb_conn)
/* Prepare statement */
int drizzle_drv_prepare(db_stmt_t *stmt, const char *query)
int drizzle_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
{
(void) len; /* unused */
/* Use client-side PS */
stmt->emulated = 1;
stmt->query = strdup(query);
@ -311,7 +311,7 @@ int drizzle_drv_prepare(db_stmt_t *stmt, const char *query)
/* Bind parameters for prepared statement */
int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
drizzle_con_st *con = (drizzle_con_st *)stmt->connection->ptr;
@ -333,7 +333,7 @@ int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Bind results for prepared statement */
int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
(void)stmt;
(void)params;
@ -345,7 +345,7 @@ int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len
/* Execute prepared statement */
int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
db_error_t drizzle_drv_execute(db_stmt_t *stmt, db_result_t *rs)
{
db_conn_t *con = stmt->connection;
char *buf = NULL;
@ -390,7 +390,7 @@ int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
}
buf[j] = '\0';
con->db_errno = drizzle_drv_query(con, buf, rs);
con->db_errno = drizzle_drv_query(con, buf, j, rs);
free(buf);
if (con->db_errno != SB_DB_ERROR_NONE)
{
@ -405,8 +405,8 @@ int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
/* Execute SQL query */
int drizzle_drv_query(db_conn_t *sb_conn, const char *query,
db_result_set_t *rs)
db_error_t drizzle_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
db_result_t *rs)
{
drizzle_con_st *con = sb_conn->ptr;
unsigned int rc;
@ -417,9 +417,9 @@ int drizzle_drv_query(db_conn_t *sb_conn, const char *query,
con,
result,
query,
strlen(query),
len,
&ret);
result= drizzle_query(con, NULL, query, strlen(query), &ret);
result= drizzle_query(con, NULL, query, len, &ret);
DEBUG("drizzle_query(%p) == %d", con, ret);
if (ret == DRIZZLE_RETURN_ERROR_CODE)
@ -468,7 +468,7 @@ int drizzle_drv_query(db_conn_t *sb_conn, const char *query,
/* Fetch row from result set of a prepared statement */
int drizzle_drv_fetch(db_result_set_t *rs)
int drizzle_drv_fetch(db_result_t *rs)
{
/* NYI */
(void)rs;
@ -481,7 +481,7 @@ int drizzle_drv_fetch(db_result_set_t *rs)
/* Fetch row from result set of a query */
int drizzle_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
int drizzle_drv_fetch_row(db_result_t *rs, db_row_t *row)
{
/* NYI */
printf("in drizzle_drv_fetch_row!\n");
@ -492,19 +492,10 @@ int drizzle_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
}
/* Return the number of rows in a result set */
unsigned long long drizzle_drv_num_rows(db_result_set_t *rs)
{
return rs->nrows;
}
/* Store results from the last query */
int drizzle_drv_store_results(db_result_set_t *rs)
int drizzle_drv_store_results(db_result_t *rs)
{
drizzle_con_st *con = rs->connection->ptr;
@ -662,13 +653,14 @@ int drizzle_drv_store_results(db_result_set_t *rs)
/* Free result set */
int drizzle_drv_free_results(db_result_set_t *rs)
int drizzle_drv_free_results(db_result_t *rs)
{
if (rs->ptr != NULL)
{
DEBUG("drizzle_result_free(%p)", rs->ptr);
drizzle_result_free(rs->ptr);
rs->ptr = NULL;
return 0;
}

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2004 MySQL AB
Copyright (C) 2004-2015 Alexey Kopytov <akopytov@gmail.com>
Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
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
@ -41,19 +41,11 @@
#include "sb_options.h"
#include "db_driver.h"
/* Check MySQL version for prepared statements availability */
#if MYSQL_VERSION_ID >= 40103
# define HAVE_PS
#endif
/* Check if we should use the TYPE= (for 3.23) or ENGINE= syntax */
#if MYSQL_VERSION_ID >= 40000
# define ENGINE_CLAUSE "ENGINE"
#else
# define ENGINE_CLAUSE "TYPE"
#endif
#define DEBUG(format, ...) do { if (args.debug) log_text(LOG_DEBUG, format, __VA_ARGS__); } while (0)
#define DEBUG(format, ...) \
do { \
if (SB_UNLIKELY(args.debug != 0)) \
log_text(LOG_DEBUG, format, __VA_ARGS__); \
} while (0)
#define SAFESTR(s) ((s != NULL) ? (s) : "(null)")
@ -114,7 +106,6 @@ typedef struct
char *socket;
} db_mysql_conn_t;
#ifdef HAVE_PS
/* Structure used for DB-to-MySQL bind types map */
typedef struct
@ -139,8 +130,6 @@ db_mysql_bind_map_t db_mysql_bind_map[] =
{DB_TYPE_NONE, 0}
};
#endif /* HAVE_PS */
/* MySQL driver capabilities */
static drv_caps_t mysql_drv_caps =
@ -169,56 +158,60 @@ static pthread_mutex_t pos_mutex;
/* MySQL driver operations */
static int mysql_drv_init(void);
static int mysql_drv_thread_init(int);
static int mysql_drv_describe(drv_caps_t *);
static int mysql_drv_connect(db_conn_t *);
static int mysql_drv_disconnect(db_conn_t *);
static int mysql_drv_prepare(db_stmt_t *, const char *);
static int mysql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
static int mysql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
static int mysql_drv_execute(db_stmt_t *, db_result_set_t *);
static int mysql_drv_fetch(db_result_set_t *);
static int mysql_drv_fetch_row(db_result_set_t *, db_row_t *);
static unsigned long long mysql_drv_num_rows(db_result_set_t *);
static int mysql_drv_query(db_conn_t *, const char *, db_result_set_t *);
static int mysql_drv_free_results(db_result_set_t *);
static int mysql_drv_prepare(db_stmt_t *, const char *, size_t);
static int mysql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
static int mysql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
static db_error_t mysql_drv_execute(db_stmt_t *, db_result_t *);
static int mysql_drv_fetch(db_result_t *);
#if 0
static int mysql_drv_fetch_row(db_result_t *, db_row_t *);
#endif
static db_error_t mysql_drv_query(db_conn_t *, const char *, size_t,
db_result_t *);
static int mysql_drv_free_results(db_result_t *);
static int mysql_drv_close(db_stmt_t *);
static int mysql_drv_store_results(db_result_set_t *);
static int mysql_drv_thread_done(int);
static int mysql_drv_done(void);
/* MySQL driver definition */
static db_driver_t mysql_driver =
{
"mysql",
"MySQL driver",
mysql_drv_args,
{
mysql_drv_init,
mysql_drv_describe,
mysql_drv_connect,
mysql_drv_disconnect,
mysql_drv_prepare,
mysql_drv_bind_param,
mysql_drv_bind_result,
mysql_drv_execute,
mysql_drv_fetch,
mysql_drv_fetch_row,
mysql_drv_num_rows,
mysql_drv_free_results,
mysql_drv_close,
mysql_drv_query,
mysql_drv_store_results,
mysql_drv_done
},
{0,0}
.sname = "mysql",
.lname = "MySQL driver",
.args = mysql_drv_args,
.ops = {
.init = mysql_drv_init,
.thread_init = mysql_drv_thread_init,
.describe = mysql_drv_describe,
.connect = mysql_drv_connect,
.disconnect = mysql_drv_disconnect,
.prepare = mysql_drv_prepare,
.bind_param = mysql_drv_bind_param,
.bind_result = mysql_drv_bind_result,
.execute = mysql_drv_execute,
.fetch = mysql_drv_fetch,
#if 0
.fetch_row = mysql_drv_fetch_row,
#else
.fetch_row = NULL,
#endif
.free_results = mysql_drv_free_results,
.close = mysql_drv_close,
.query = mysql_drv_query,
.thread_done = mysql_drv_thread_done,
.done = mysql_drv_done
}
};
/* Local functions */
#ifdef HAVE_PS
static int get_mysql_bind_type(db_bind_type_t);
#endif
/* Register MySQL driver */
@ -272,11 +265,9 @@ int mysql_drv_init(void)
args.dry_run = sb_get_value_flag("mysql-dry-run");
use_ps = 0;
#ifdef HAVE_PS
mysql_drv_caps.prepared_statements = 1;
if (db_globals.ps_mode != DB_PS_MODE_DISABLE)
use_ps = 1;
#endif
DEBUG("mysql_library_init(%d, %p, %p)", 0, NULL, NULL);
mysql_library_init(0, NULL, NULL);
@ -284,10 +275,28 @@ int mysql_drv_init(void)
return 0;
}
/* Thread-local driver initialization */
int mysql_drv_thread_init(int thread_id)
{
(void) thread_id; /* unused */
return mysql_thread_init() != 0;
}
/* Thread-local driver deinitialization */
int mysql_drv_thread_done(int thread_id)
{
(void) thread_id; /* unused */
mysql_thread_end();
return 0;
}
/* Describe database capabilities */
int mysql_drv_describe(drv_caps_t *caps)
{
*caps = mysql_drv_caps;
@ -474,9 +483,8 @@ int mysql_drv_disconnect(db_conn_t *sb_conn)
/* Prepare statement */
int mysql_drv_prepare(db_stmt_t *stmt, const char *query)
int mysql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
{
#ifdef HAVE_PS
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) stmt->connection->ptr;
MYSQL *con = db_mysql_con->mysql;
MYSQL_STMT *mystmt;
@ -499,8 +507,8 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query)
}
stmt->ptr = (void *)mystmt;
DEBUG("mysql_stmt_prepare(%p, \"%s\", %u) = %p", mystmt, query,
(unsigned int) strlen(query), stmt->ptr);
if (mysql_stmt_prepare(mystmt, query, strlen(query)))
(unsigned int) len, stmt->ptr);
if (mysql_stmt_prepare(mystmt, query, len))
{
/* Check if this statement in not supported */
rc = mysql_errno(con);
@ -522,13 +530,15 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query)
return 1;
}
}
stmt->query = strdup(query);
stmt->stat_type = (mysql_stmt_field_count(mystmt) > 0) ?
DB_STAT_READ : DB_STAT_WRITE;
return 0;
}
emulate:
#endif /* HAVE_PS */
/* Use client-side PS */
stmt->emulated = 1;
@ -541,16 +551,14 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query)
/* Bind parameters for prepared statement */
int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) stmt->connection->ptr;
MYSQL *con = db_mysql_con->mysql;
#ifdef HAVE_PS
MYSQL_BIND *bind;
unsigned int i;
my_bool rc;
unsigned long param_count;
#endif
if (args.dry_run)
return 0;
@ -558,7 +566,6 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
if (con == NULL)
return 1;
#ifdef HAVE_PS
if (!stmt->emulated)
{
if (stmt->ptr == NULL)
@ -598,7 +605,6 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
return 0;
}
#endif /* HAVE_PS */
/* Use emulation */
if (stmt->bound_param != NULL)
@ -617,16 +623,8 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Bind results for prepared statement */
int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
#ifndef HAVE_PS
/* No support for prepared statements */
(void)stmt; /* unused */
(void)params; /* unused */
(void)len; /* unused */
return 1;
#else
db_mysql_conn_t *db_mysql_con =(db_mysql_conn_t *) stmt->connection->ptr;
MYSQL *con = db_mysql_con->mysql;
MYSQL_BIND *bind;
@ -662,14 +660,9 @@ int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
free(bind);
return 0;
#endif /* HAVE_PS */
}
/*
Reset connection to the server by reconnecting with the same parameters.
*/
/* Reset connection to the server by reconnecting with the same parameters. */
static int mysql_drv_reconnect(db_conn_t *sb_con)
{
@ -684,14 +677,14 @@ static int mysql_drv_reconnect(db_conn_t *sb_con)
while (mysql_drv_real_connect(db_mysql_con))
{
if (sb_globals.error)
return SB_DB_ERROR_FAILED;
return DB_ERROR_FATAL;
usleep(1000);
}
log_text(LOG_DEBUG, "Reconnected");
return SB_DB_ERROR_RECONNECTED;
return DB_ERROR_IGNORABLE;
}
@ -701,7 +694,8 @@ static int mysql_drv_reconnect(db_conn_t *sb_con)
*/
static int check_error(db_conn_t *sb_con, const char *func, const char *query)
static db_error_t check_error(db_conn_t *sb_con, const char *func,
const char *query, db_stat_type_t *type)
{
sb_list_item_t *pos;
unsigned int tmp;
@ -734,6 +728,8 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query)
case CR_TCP_CONNECTION:
case CR_SERVER_LOST_EXTENDED:
*type = DB_STAT_RECONNECT;
return mysql_drv_reconnect(sb_con);
default:
@ -741,7 +737,9 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query)
break;
}
return SB_DB_ERROR_RESTART_TRANSACTION;
*type = DB_STAT_ERROR;
return DB_ERROR_IGNORABLE;
}
}
@ -752,13 +750,15 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query)
log_text(LOG_ALERT, "%s returned error %u (%s)",
func, error, mysql_error(con));
return SB_DB_ERROR_FAILED;
*type = DB_STAT_ERROR;
return DB_ERROR_FATAL;
}
/* Execute prepared statement */
int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
db_error_t mysql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
{
db_conn_t *con = stmt->connection;
char *buf = NULL;
@ -766,32 +766,51 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
unsigned int i, j, vcnt;
char need_realloc;
int n;
unsigned int rc;
if (args.dry_run)
return 0;
#ifdef HAVE_PS
(void)rs; /* unused */
return DB_ERROR_NONE;
if (!stmt->emulated)
{
if (stmt->ptr == NULL)
{
log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), uninitialized statement");
return SB_DB_ERROR_FAILED;
log_text(LOG_DEBUG,
"ERROR: exiting mysql_drv_execute(), uninitialized statement");
return DB_ERROR_FATAL;
}
rc = (unsigned int)mysql_stmt_execute(stmt->ptr);
DEBUG("mysql_stmt_execute(%p) = %u", stmt->ptr, rc);
if (rc)
return check_error(con, "mysql_stmt_execute()", stmt->query);
int err = mysql_stmt_execute(stmt->ptr);
DEBUG("mysql_stmt_execute(%p) = %d", stmt->ptr, err);
return SB_DB_ERROR_NONE;
if (err)
return check_error(con, "mysql_stmt_execute()", stmt->query,
&rs->stat_type);
if (stmt->stat_type != DB_STAT_READ)
{
rs->nrows = (uint32_t) mysql_stmt_affected_rows(stmt->ptr);
DEBUG("mysql_stmt_affected_rows(%p) = %u", stmt->ptr,
(unsigned) rs->nrows);
rs->stat_type = (rs->nrows > 0) ? DB_STAT_WRITE : DB_STAT_OTHER;
return DB_ERROR_NONE;
}
err = mysql_stmt_store_result(stmt->ptr);
DEBUG("mysql_stmt_store_result(%p) = %d", stmt->ptr, err);
if (err)
{
return check_error(con, "mysql_stmt_store_result()", NULL,
&rs->stat_type);
}
rs->nrows = (uint32_t) mysql_stmt_num_rows(stmt->ptr);
DEBUG("mysql_stmt_num_rows(%p) = %u", rs->statement->ptr,
(unsigned) (rs->nrows));
return DB_ERROR_NONE;
}
#else
(void)rc; /* unused */
#endif /* HAVE_PS */
/* Use emulation */
/* Build the actual query string from parameters list */
@ -807,7 +826,7 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
if (buf == NULL)
{
log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), memory allocation failure");
return SB_DB_ERROR_FAILED;
return DB_ERROR_FATAL;
}
need_realloc = 0;
}
@ -829,51 +848,73 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
}
buf[j] = '\0';
con->db_errno = mysql_drv_query(con, buf, rs);
free(buf);
if (con->db_errno != SB_DB_ERROR_NONE)
{
log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), database error");
return con->db_errno;
}
db_error_t rc = mysql_drv_query(con, buf, j, rs);
return SB_DB_ERROR_NONE;
free(buf);
return rc;
}
/* Execute SQL query */
int mysql_drv_query(db_conn_t *sb_conn, const char *query,
db_result_set_t *rs)
db_error_t mysql_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
db_result_t *rs)
{
db_mysql_conn_t *db_mysql_con;
MYSQL *con;
unsigned int rc;
(void)rs; /* unused */
if (args.dry_run)
return 0;
return DB_ERROR_NONE;
db_mysql_con = (db_mysql_conn_t *)sb_conn->ptr;
con = db_mysql_con->mysql;
rc = (unsigned int)mysql_real_query(con, query, strlen(query));
DEBUG("mysql_real_query(%p, \"%s\", %u) = %u", con, query,
(unsigned int) strlen(query), rc);
int err = mysql_real_query(con, query, len);
DEBUG("mysql_real_query(%p, \"%s\", %zd) = %d", con, query, len, err);
if (rc)
return check_error(sb_conn, "mysql_drv_query()", query);
if (SB_UNLIKELY(err != 0))
return check_error(sb_conn, "mysql_drv_query()", query, &rs->stat_type);
return SB_DB_ERROR_NONE;
/* Store results and get query type */
MYSQL_RES *res = mysql_store_result(con);
DEBUG("mysql_store_result(%p) = %p", con, res);
if (res == NULL)
{
if (mysql_errno(con) == 0 && mysql_field_count(con) == 0)
{
/* Not a select. Check if it was a DML */
uint32_t nrows = (uint32_t) mysql_affected_rows(con);
if (nrows > 0)
{
rs->stat_type = DB_STAT_WRITE;
rs->nrows = nrows;
}
else
rs->stat_type = DB_STAT_OTHER;
return DB_ERROR_NONE;
}
return check_error(sb_conn, "mysql_store_result()", NULL, &rs->stat_type);
}
rs->stat_type = DB_STAT_READ;
rs->ptr = (void *)res;
rs->nrows = mysql_num_rows(res);
DEBUG("mysql_num_rows(%p) = %u", res, (unsigned int)rs->nrows);
return DB_ERROR_NONE;
}
/* Fetch row from result set of a prepared statement */
int mysql_drv_fetch(db_result_set_t *rs)
int mysql_drv_fetch(db_result_t *rs)
{
/* NYI */
(void)rs; /* unused */
@ -882,10 +923,11 @@ int mysql_drv_fetch(db_result_set_t *rs)
}
#if 0
/* Fetch row from result set of a query */
int mysql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
int mysql_drv_fetch_row(db_result_t *rs, db_row_t *row)
{
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) rs->connection->ptr;
row->ptr = mysql_fetch_row(rs->ptr);
@ -899,110 +941,31 @@ int mysql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
return 0;
}
/* Return the number of rows in a result set */
unsigned long long mysql_drv_num_rows(db_result_set_t *rs)
{
return args.dry_run ? 0 : rs->nrows;
}
/* Store results from the last query */
int mysql_drv_store_results(db_result_set_t *rs)
{
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) rs->connection->ptr;
MYSQL *con;
MYSQL_RES *res;
MYSQL_ROW row;
unsigned int rc;
if (args.dry_run)
return 0;
con = db_mysql_con->mysql;
#ifdef HAVE_PS
/* Is this result set from prepared statement? */
if (rs->statement != NULL && rs->statement->emulated == 0)
{
if (rs->statement->ptr == NULL)
return 1;
rc = (unsigned int)mysql_stmt_store_result(rs->statement->ptr);
DEBUG("mysql_stmt_store_result(%p) = %d", rs->statement->ptr, rc);
if (rc)
{
if (mysql_stmt_field_count(rs->statement->ptr) == 0)
return SB_DB_ERROR_NONE;
return check_error(rs->connection, "mysql_stmt_store_result()", NULL);
}
rs->nrows = mysql_stmt_num_rows(rs->statement->ptr);
DEBUG("mysql_stmt_num_rows(%p) = %llu", rs->statement->ptr, rs->nrows);
do {
rc = (unsigned int)mysql_stmt_fetch(rs->statement->ptr);
DEBUG("mysql_stmt_fetch(%p) = %d", rs->statement->ptr, rc);
} while(rc == 0);
return SB_DB_ERROR_NONE;
}
#endif
if (con == NULL)
return SB_DB_ERROR_FAILED;
/* using store results for speed will not work for large sets */
res = mysql_store_result(con);
DEBUG("mysql_store_result(%p) = %p", con, res);
if (res == NULL)
{
if (mysql_field_count(con) == 0)
return SB_DB_ERROR_NONE;
return check_error(rs->connection, "mysql_store_result()", NULL);
}
rs->ptr = (void *)res;
rs->nrows = mysql_num_rows(res);
DEBUG("mysql_num_rows(%p) = %llu", res, rs->nrows);
/* just fetch result */
while((row = mysql_fetch_row(res)))
DEBUG("mysql_fetch_row(%p) = %p", res, row);
return SB_DB_ERROR_NONE;
}
/* Free result set */
int mysql_drv_free_results(db_result_set_t *rs)
int mysql_drv_free_results(db_result_t *rs)
{
if (args.dry_run)
return 0;
#ifdef HAVE_PS
/* Is this a result set of a prepared statement */
/* Is this a result set of a prepared statement? */
if (rs->statement != NULL && rs->statement->emulated == 0)
{
DEBUG("mysql_stmt_free_result(%p)", rs->statement->ptr);
return mysql_stmt_free_result(rs->statement->ptr);
mysql_stmt_free_result(rs->statement->ptr);
rs->ptr = NULL;
}
#endif
if (rs->ptr != NULL)
{
DEBUG("mysql_free_result(%p)", rs->ptr);
mysql_free_result((MYSQL_RES *)rs->ptr);
return 0;
rs->ptr = NULL;
}
return 1;
return 0;
}
@ -1020,16 +983,11 @@ int mysql_drv_close(db_stmt_t *stmt)
stmt->query = NULL;
}
#ifdef HAVE_PS
if (stmt->ptr == NULL)
return 1;
DEBUG("mysql_stmt_close(%p)", stmt->ptr);
return mysql_stmt_close(stmt->ptr);
#else
(void)stmt; /* unused */
return 0;
#endif
}
@ -1044,11 +1002,8 @@ int mysql_drv_done(void)
return 0;
}
#ifdef HAVE_PS
/* Map SQL data type to bind_type value in MYSQL_BIND */
int get_mysql_bind_type(db_bind_type_t type)
{
unsigned int i;
@ -1059,5 +1014,3 @@ int get_mysql_bind_type(db_bind_type_t type)
return -1;
}
#endif /* HAVE_PS */

View File

@ -170,17 +170,17 @@ static int ora_drv_init(void);
static int ora_drv_describe(drv_caps_t *);
static int ora_drv_connect(db_conn_t *);
static int ora_drv_disconnect(db_conn_t *);
static int ora_drv_prepare(db_stmt_t *, const char *);
static int ora_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
static int ora_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
static int ora_drv_execute(db_stmt_t *, db_result_set_t *);
static int ora_drv_fetch(db_result_set_t *);
static int ora_drv_fetch_row(db_result_set_t *, db_row_t *);
static unsigned long long ora_drv_num_rows(db_result_set_t *);
static int ora_drv_query(db_conn_t *, const char *, db_result_set_t *);
static int ora_drv_free_results(db_result_set_t *);
static int ora_drv_prepare(db_stmt_t *, const char *, size_t);
static int ora_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
static int ora_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
static db_error_t ora_drv_execute(db_stmt_t *, db_result_t *);
static int ora_drv_fetch(db_result_t *);
static int ora_drv_fetch_row(db_result_t *, db_row_t *);
static db_error_t ora_drv_query(db_conn_t *, const char *, size_t,
db_result_t *);
static int ora_drv_free_results(db_result_t *);
static int ora_drv_close(db_stmt_t *);
static int ora_drv_store_results(db_result_set_t *);
static int ora_drv_store_results(db_result_t *);
static int ora_drv_done(void);
/* Oracle driver definition */
@ -192,24 +192,22 @@ static db_driver_t oracle_driver =
.args = ora_drv_args,
.ops =
{
ora_drv_init,
ora_drv_describe,
ora_drv_connect,
ora_drv_disconnect,
ora_drv_prepare,
ora_drv_bind_param,
ora_drv_bind_result,
ora_drv_execute,
ora_drv_fetch,
ora_drv_fetch_row,
ora_drv_num_rows,
ora_drv_free_results,
ora_drv_close,
ora_drv_query,
ora_drv_store_results,
ora_drv_done
},
.listitem = {NULL, NULL}
.init = ora_drv_init,
.describe = ora_drv_describe,
.connect = ora_drv_connect,
.disconnect = ora_drv_disconnect,
.prepare = ora_drv_prepare,
.bind_param = ora_drv_bind_param,
.bind_result = ora_drv_bind_result,
.execute = ora_drv_execute,
.fetch = ora_drv_fetch,
.fetch_row = ora_drv_fetch_row,
.free_results = ora_drv_free_results,
.close = ora_drv_close,
.query = ora_drv_query,
.store_results = ora_drv_store_results,
.done = ora_drv_done
}
};
@ -402,7 +400,7 @@ int ora_drv_disconnect(db_conn_t *sb_conn)
/* Prepare statement */
int ora_drv_prepare(db_stmt_t *stmt, const char *query)
int ora_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
{
ora_conn_t *ora_con = (ora_conn_t *)stmt->connection->ptr;
sword rc;
@ -468,7 +466,7 @@ int ora_drv_prepare(db_stmt_t *stmt, const char *query)
if (ora_stmt->type != STMT_TYPE_BEGIN &&
ora_stmt->type != STMT_TYPE_COMMIT)
{
rc = OCIStmtPrepare(ora_stmt->ptr, ora_con->errhp, buf, strlen(buf),
rc = OCIStmtPrepare(ora_stmt->ptr, ora_con->errhp, buf, j,
OCI_NTV_SYNTAX, OCI_DEFAULT);
CHECKERR("OCIStmtPrepare");
@ -507,7 +505,7 @@ int ora_drv_prepare(db_stmt_t *stmt, const char *query)
/* Bind parameters for prepared statement */
int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
ora_conn_t *con = (ora_conn_t *)stmt->connection->ptr;
ora_stmt_t *ora_stmt = (ora_stmt_t *)stmt->ptr;
@ -574,7 +572,7 @@ int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Bind results for prepared statement */
int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
/* NYI */
@ -589,7 +587,7 @@ int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Execute prepared statement */
int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
db_error_t ora_drv_execute(db_stmt_t *stmt, db_result_t *rs)
{
db_conn_t *db_con = stmt->connection;
ora_stmt_t *ora_stmt = stmt->ptr;
@ -675,7 +673,7 @@ int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
}
buf[j] = '\0';
db_con->db_errno = ora_drv_query(db_con, buf, rs);
db_con->db_errno = ora_drv_query(db_con, buf, j, rs);
free(buf);
return SB_DB_ERROR_NONE;
@ -690,8 +688,8 @@ int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
/* Execute SQL query */
int ora_drv_query(db_conn_t *sb_conn, const char *query,
db_result_set_t *rs)
db_error_t ora_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
db_result_t *rs)
{
ora_conn_t *ora_con = sb_conn->ptr;
sword rc = 0;
@ -728,7 +726,7 @@ int ora_drv_query(db_conn_t *sb_conn, const char *query,
stmt = (OCIStmt *)tmp;
rc = OCIStmtPrepare(stmt, ora_con->errhp, (OraText *)query, strlen(query),
rc = OCIStmtPrepare(stmt, ora_con->errhp, (OraText *)query, len,
OCI_NTV_SYNTAX, OCI_DEFAULT);
CHECKERR("OCIStmtPrepare");
@ -752,7 +750,7 @@ int ora_drv_query(db_conn_t *sb_conn, const char *query,
/* Fetch row from result set of a prepared statement */
int ora_drv_fetch(db_result_set_t *rs)
int ora_drv_fetch(db_result_t *rs)
{
/* NYI */
(void)rs;
@ -764,7 +762,7 @@ int ora_drv_fetch(db_result_set_t *rs)
/* Fetch row from result set of a query */
int ora_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
int ora_drv_fetch_row(db_result_t *rs, db_row_t *row)
{
/* NYI */
(void)rs; /* unused */
@ -774,25 +772,10 @@ int ora_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
}
/* Return the number of rows in a result set */
unsigned long long ora_drv_num_rows(db_result_set_t *rs)
{
ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr;
/* Check if the results are already fetched */
if (ora_rs != NULL)
return ora_rs->nrows;
return 0;
}
/* Store results from the last query */
int ora_drv_store_results(db_result_set_t *rs)
int ora_drv_store_results(db_result_t *rs)
{
unsigned int i;
sword rc;
@ -935,7 +918,7 @@ int ora_drv_store_results(db_result_set_t *rs)
/* Free result set */
int ora_drv_free_results(db_result_set_t *rs)
int ora_drv_free_results(db_result_t *rs)
{
ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr;
ora_row_t *row;
@ -979,7 +962,9 @@ int ora_drv_free_results(db_result_set_t *rs)
}
free(ora_rs);
rs->ptr = NULL;
return 0;
}

View File

@ -114,17 +114,16 @@ static int pgsql_drv_init(void);
static int pgsql_drv_describe(drv_caps_t *);
static int pgsql_drv_connect(db_conn_t *);
static int pgsql_drv_disconnect(db_conn_t *);
static int pgsql_drv_prepare(db_stmt_t *, const char *);
static int pgsql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
static int pgsql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
static int pgsql_drv_execute(db_stmt_t *, db_result_set_t *);
static int pgsql_drv_fetch(db_result_set_t *);
static int pgsql_drv_fetch_row(db_result_set_t *, db_row_t *);
static unsigned long long pgsql_drv_num_rows(db_result_set_t *);
static int pgsql_drv_query(db_conn_t *, const char *, db_result_set_t *);
static int pgsql_drv_free_results(db_result_set_t *);
static int pgsql_drv_prepare(db_stmt_t *, const char *, size_t);
static int pgsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
static int pgsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
static db_error_t pgsql_drv_execute(db_stmt_t *, db_result_t *);
static int pgsql_drv_fetch(db_result_t *);
static int pgsql_drv_fetch_row(db_result_t *, db_row_t *);
static db_error_t pgsql_drv_query(db_conn_t *, const char *, size_t,
db_result_t *);
static int pgsql_drv_free_results(db_result_t *);
static int pgsql_drv_close(db_stmt_t *);
static int pgsql_drv_store_results(db_result_set_t *);
static int pgsql_drv_done(void);
/* PgSQL driver definition */
@ -136,24 +135,21 @@ static db_driver_t pgsql_driver =
.args = pgsql_drv_args,
.ops =
{
pgsql_drv_init,
pgsql_drv_describe,
pgsql_drv_connect,
pgsql_drv_disconnect,
pgsql_drv_prepare,
pgsql_drv_bind_param,
pgsql_drv_bind_result,
pgsql_drv_execute,
pgsql_drv_fetch,
pgsql_drv_fetch_row,
pgsql_drv_num_rows,
pgsql_drv_free_results,
pgsql_drv_close,
pgsql_drv_query,
pgsql_drv_store_results,
pgsql_drv_done
},
.listitem = {NULL, NULL}
.init = pgsql_drv_init,
.describe = pgsql_drv_describe,
.connect = pgsql_drv_connect,
.disconnect = pgsql_drv_disconnect,
.prepare = pgsql_drv_prepare,
.bind_param = pgsql_drv_bind_param,
.bind_result = pgsql_drv_bind_result,
.execute = pgsql_drv_execute,
.fetch = pgsql_drv_fetch,
.fetch_row = pgsql_drv_fetch_row,
.free_results = pgsql_drv_free_results,
.close = pgsql_drv_close,
.query = pgsql_drv_query,
.done = pgsql_drv_done
}
};
@ -273,7 +269,7 @@ int pgsql_drv_disconnect(db_conn_t *sb_conn)
/* Prepare statement */
int pgsql_drv_prepare(db_stmt_t *stmt, const char *query)
int pgsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
{
PGconn *con = (PGconn *)stmt->connection->ptr;
PGresult *pgres;
@ -285,7 +281,9 @@ int pgsql_drv_prepare(db_stmt_t *stmt, const char *query)
unsigned int buflen;
int n;
char name[32];
(void) len; /* unused */
if (con == NULL)
return 1;
@ -375,7 +373,7 @@ int pgsql_drv_prepare(db_stmt_t *stmt, const char *query)
/* Bind parameters for prepared statement */
int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
PGconn *con = (PGconn *)stmt->connection->ptr;
PGresult *pgres;
@ -405,7 +403,7 @@ int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
if ((unsigned)pgstmt->nparams != len)
{
log_text(LOG_ALERT, "wrong number of parameters in prepared statement");
log_text(LOG_DEBUG, "counted: %d, passed to bind_param(): %d",
log_text(LOG_DEBUG, "counted: %d, passed to bind_param(): %zd",
pgstmt->nparams, len);
return 1;
}
@ -454,7 +452,7 @@ int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Bind results for prepared statement */
int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
{
/* unused */
(void)stmt;
@ -468,35 +466,67 @@ int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
/* Check query execution status */
static int pgsql_check_status(PGconn *pgcon, PGresult *pgres,
const char *funcname)
static db_error_t pgsql_check_status(PGconn *pgcon, PGresult *pgres,
const char *funcname, const char *query,
db_result_t *rs)
{
ExecStatusType status;
db_error_t rc;
status = PQresultStatus(pgres);
if (status != PGRES_TUPLES_OK && status != PGRES_COMMAND_OK)
{
switch(status) {
case PGRES_TUPLES_OK:
rs->nrows = PQntuples(pgres);
rs->stat_type = DB_STAT_READ;
rc = DB_ERROR_NONE;
break;
case PGRES_COMMAND_OK:
rs->nrows = strtoul(PQcmdTuples(pgres), NULL, 10);;
rs->stat_type = (rs->nrows > 0) ? DB_STAT_WRITE : DB_STAT_OTHER;
rc = DB_ERROR_NONE;
break;
case PGRES_FATAL_ERROR:
rs->nrows = 0;
rs->stat_type = DB_STAT_ERROR;
const char * const errmsg = PQerrorMessage(pgcon);
if (strstr(errmsg, "deadlock detected") ||
strstr(errmsg, "duplicate key value violates unique constraint"))
{
PQexec(pgcon, "ROLLBACK");
return SB_DB_ERROR_RESTART_TRANSACTION;
rc = DB_ERROR_IGNORABLE;
}
else
{
log_text(LOG_FATAL, "%s() failed: %d %s", funcname, status, errmsg);
if (query != NULL)
log_text(LOG_FATAL, "failed query was: %s", query);
rc = DB_ERROR_FATAL;
}
log_text(LOG_FATAL, "%s() failed: %d %s", funcname, status, errmsg);
return SB_DB_ERROR_FAILED;
break;
default:
rs->nrows = 0;
rs->stat_type = DB_STAT_OTHER;
rc = DB_ERROR_NONE;
}
return SB_DB_ERROR_NONE;
return rc;
}
/* Execute prepared statement */
int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
db_error_t pgsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
{
db_conn_t *con = stmt->connection;
PGconn *pgcon = (PGconn *)con->ptr;
@ -507,15 +537,18 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
unsigned int i, j, vcnt;
char need_realloc;
int n;
int rc;
db_error_t rc;
if (!stmt->emulated)
{
pgstmt = stmt->ptr;
if (pgstmt == NULL)
return SB_DB_ERROR_FAILED;
{
log_text(LOG_DEBUG,
"ERROR: exiting mysql_drv_execute(), uninitialized statement");
return DB_ERROR_FATAL;
}
/* Convert SysBench bind structures to PgSQL data */
for (i = 0; i < (unsigned)pgstmt->nparams; i++)
{
@ -537,10 +570,9 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
pgres = PQexecPrepared(pgcon, pgstmt->name, pgstmt->nparams,
(const char **)pgstmt->pvalues, NULL, NULL, 1);
rc = pgsql_check_status(pgcon, pgres, "PQexecPrepared");
rc = pgsql_check_status(pgcon, pgres, "PQexecPrepared", NULL, rs);
if (rc == SB_DB_ERROR_NONE)
rs->ptr = (void *)pgres;
rs->ptr = (void *) pgres;
return rc;
}
@ -557,7 +589,7 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
buflen = (buflen > 0) ? buflen * 2 : 256;
buf = realloc(buf, buflen);
if (buf == NULL)
return SB_DB_ERROR_FAILED;
return DB_ERROR_FATAL;
need_realloc = 0;
}
@ -577,37 +609,31 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
vcnt++;
}
buf[j] = '\0';
con->db_errno = pgsql_drv_query(con, buf, rs);
free(buf);
if (con->db_errno != SB_DB_ERROR_NONE)
{
return con->db_errno;
}
return SB_DB_ERROR_NONE;
rc = pgsql_drv_query(con, buf, j, rs);
free(buf);
return rc;
}
/* Execute SQL query */
int pgsql_drv_query(db_conn_t *sb_conn, const char *query,
db_result_set_t *rs)
db_error_t pgsql_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
db_result_t *rs)
{
PGconn *con = sb_conn->ptr;
PGresult *pgres;
int rc;
db_error_t rc;
(void)rs; /* unused */
(void)len; /* unused */
pgres = PQexec(con, query);
rc = pgsql_check_status(con, pgres, "PQexec");
rc = pgsql_check_status(con, pgres, "PQexec", query, rs);
if (rc == SB_DB_ERROR_NONE)
rs->ptr = pgres;
else if (rc == SB_DB_ERROR_FAILED)
log_text(LOG_FATAL, "failed query: %s", query);
rs->ptr = pgres;
return rc;
}
@ -616,7 +642,7 @@ int pgsql_drv_query(db_conn_t *sb_conn, const char *query,
/* Fetch row from result set of a prepared statement */
int pgsql_drv_fetch(db_result_set_t *rs)
int pgsql_drv_fetch(db_result_t *rs)
{
/* NYI */
(void)rs;
@ -628,7 +654,7 @@ int pgsql_drv_fetch(db_result_set_t *rs)
/* Fetch row from result set of a query */
int pgsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
int pgsql_drv_fetch_row(db_result_t *rs, db_row_t *row)
{
/* NYI */
(void)rs; /* unused */
@ -638,46 +664,15 @@ int pgsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
}
/* Return the number of rows in a result set */
unsigned long long pgsql_drv_num_rows(db_result_set_t *rs)
{
return rs->nrows;
}
/* Store results from the last query */
int pgsql_drv_store_results(db_result_set_t *rs)
{
PGresult *pgres;
unsigned long long i,j, ncolumns;
pgres = (PGresult *)rs->ptr;
if (pgres == NULL)
return 1;
rs->nrows = PQntuples(pgres);
ncolumns = PQnfields(pgres);
for (i = 0; i < rs->nrows; i++)
for (j = 0; j < ncolumns; j++)
PQgetvalue(pgres, i, j);
return 0;
}
/* Free result set */
int pgsql_drv_free_results(db_result_set_t *rs)
int pgsql_drv_free_results(db_result_t *rs)
{
if (rs->ptr != NULL)
{
PQclear((PGresult *)rs->ptr);
rs->ptr = NULL;
return 0;
}

View File

@ -15,3 +15,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SUBDIRS = internal
dist_pkgdata_DATA = common.lua oltp.lua

View File

@ -14,10 +14,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
BUILT_SOURCES = sysbench.lua.h
CLEARFILES = sysbench.lua.h
BUILT_SOURCES = sysbench.lua.h sysbench.sql.lua.h
CLEARFILES = sysbench.lua.h sysbench.sql.lua.h
EXTRA_DIST = sysbench.lua
EXTRA_DIST = sysbench.lua sysbench.sql.lua
SUFFIXES = .lua .lua.h

View File

@ -1,4 +1,4 @@
-- Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
-- Copyright (C) 2016-2017 Alexey Kopytov <akopytov@gmail.com>
-- 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
@ -82,8 +82,7 @@ thread_id = sysbench.tid
function sb_rnd()
-- Keep lower 32 bits from sysbench.rand.uniform_uint64() and convert them to
-- a Lua number
return tonumber(sysbench.rand.uniform_uint64() %
tonumber("100000000", 16))
return tonumber(sysbench.rand.uniform_uint64() % 4294967296)
end
sb_rand = sysbench.rand.default
@ -106,7 +105,6 @@ function sb_rand_uniq(a, b)
return res
end
db_connect = sysbench.db.connect
db_disconnect = sysbench.db.disconnect
@ -134,9 +132,6 @@ DB_ERROR_FAILED = sysbench.db.DB_ERROR_FAILED
-- Main event loop. This is a Lua version of sysbench.c:thread_run()
-- ----------------------------------------------------------------------
function thread_run(thread_id)
if (type(event) ~= "function") then
error("Cannot find the 'event' function in the script")
end
while sysbench.more_events() do
sysbench.event_start()
event(thread_id)

View File

@ -0,0 +1,223 @@
-- Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
-- 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; either version 2 of the License, or
-- (at your option) any later version.
-- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- SQL API
-- ----------------------------------------------------------------------
ffi = require("ffi")
sysbench.sql = {}
ffi.cdef[[
typedef enum
{
DB_ERROR_NONE, /* no error(s) */
DB_ERROR_IGNORABLE, /* error should be ignored as defined by command
line arguments or a custom error handler */
DB_ERROR_FATAL /* non-ignorable error */
} sql_error_t;
typedef struct db_driver sql_driver;
typedef struct db_conn sql_connection;
typedef struct db_stmt sql_statement;
typedef struct db_result sql_result;
typedef enum
{
SQL_TYPE_NONE,
SQL_TYPE_TINYINT,
SQL_TYPE_SMALLINT,
SQL_TYPE_INT,
SQL_TYPE_BIGINT,
SQL_TYPE_FLOAT,
SQL_TYPE_DOUBLE,
SQL_TYPE_TIME,
SQL_TYPE_DATE,
SQL_TYPE_DATETIME,
SQL_TYPE_TIMESTAMP,
SQL_TYPE_CHAR,
SQL_TYPE_VARCHAR
} sql_bind_type_t;
typedef struct
{
sql_bind_type_t type;
void *buffer;
unsigned long *data_len;
unsigned long max_len;
char *is_null;
} sql_bind;
sql_driver *db_create(const char *);
int db_destroy(sql_driver *drv);
sql_connection *db_connection_create(sql_driver * drv);
int db_connection_close(sql_connection *con);
void db_connection_free(sql_connection *con);
int db_bulk_insert_init(sql_connection *, const char *, size_t);
int db_bulk_insert_next(sql_connection *, const char *, size_t);
void db_bulk_insert_done(sql_connection *);
sql_result *db_query(sql_connection *con, const char *query, size_t len);
sql_statement *db_prepare(sql_connection *con, const char *query, size_t len);
int db_bind_param(sql_statement *stmt, sql_bind *params, size_t len);
int db_bind_result(sql_statement *stmt, sql_bind *results, size_t len);
sql_result db_execute(sql_statement *stmt);
int db_close(sql_statement *stmt);
]]
local sql_driver = ffi.typeof('sql_driver *')
local sql_connection = ffi.typeof('sql_connection *')
local sql_statement = ffi.typeof('sql_statement *')
local sql_bind = ffi.typeof('sql_bind');
sysbench.sql.type =
{
NONE = ffi.C.SQL_TYPE_NONE,
TINYINT = ffi.C.SQL_TYPE_TINYINT,
SMALLINT = ffi.C.SQL_TYPE_SMALLINT,
INT = ffi.C.SQL_TYPE_INT,
BIGINT = ffi.C.SQL_TYPE_BIGINT,
FLOAT = ffi.C.SQL_TYPE_FLOAT,
DOUBLE = ffi.C.SQL_TYPE_DOUBLE,
TIME = ffi.C.SQL_TYPE_TIME,
DATE = ffi.C.SQL_TYPE_DATE,
DATETIME = ffi.C.SQL_TYPE_DATETIME,
TIMESTAMP = ffi.C.SQL_TYPE_TIMESTAMP,
CHAR = ffi.C.SQL_TYPE_CHAR,
VARCHAR = ffi.C.SQL_TYPE_VARCHAR
}
local function check_type(type, var, func)
if var == nil or not ffi.istype(type, var) then
error(string.format("bad argument '%s' to %s() where a '%s' was expected",
var, func, type))
end
end
-- Initialize a given SQL driver and return a handle to it to create
-- connections. A nil driver name (i.e. no function argument) initializes the
-- default driver, i.e. the one specified with --db-driver on the command line.
function sysbench.sql.driver(driver_name)
local drv = ffi.C.db_create(driver_name)
if (drv == nil) then
error("failed to initialize the DB driver")
end
return ffi.gc(drv, ffi.C.db_destroy)
end
function sysbench.sql.connect(driver)
check_type(sql_driver, driver, 'sysbench.sql.connect')
local con = ffi.C.db_connection_create(driver)
if con == nil then
error('connection creation failed')
end
return ffi.gc(con, ffi.C.db_connection_free)
end
function sysbench.sql.disconnect(con)
check_type(sql_connection, con, 'sysbench.sql.disconnect')
return ffi.C.db_connection_close(con) == 0
end
function sysbench.sql.query(con, query)
check_type(sql_connection, con, 'sysbench.sql.query')
return ffi.C.db_query(con, query, #query)
end
function sysbench.sql.bulk_insert_init(con, query)
check_type(sql_connection, con, 'sysbench.sql.bulk_insert_init')
return ffi.C.db_bulk_insert_init(con, query, #query)
end
function sysbench.sql.bulk_insert_next(con, val)
check_type(sql_connection, con, 'sysbench.sql.bulk_insert_next')
return ffi.C.db_bulk_insert_next(con, val, #val)
end
function sysbench.sql.bulk_insert_done(con)
check_type(sql_connection, con, 'sysbench.sql.bulk_insert_done')
return ffi.C.db_bulk_insert_done(con)
end
function sysbench.sql.prepare(con, query)
check_type(sql_connection, con, 'sysbench.sql.prepare')
return ffi.C.db_prepare(con, query, #query)
end
function sysbench.sql.bind_param(stmt, params)
local len = #params
local sql_params = {}
local i
check_type(sql_statement, stmt, 'sysbench.sql.bind_param')
error("NYI")
return ffi.C.db_bind_param(stmt,
ffi.new("sql_bind[" .. len .."]",
sql_params),
len)
end
-- sql_driver metatable
local driver_mt = {
__index = {
connect = sysbench.sql.connect,
},
__gc = ffi.C.db_destroy,
__tostring = function() return '<sql_driver>' end,
}
ffi.metatype("struct db_driver", driver_mt)
-- sql_connection metatable
local connection_mt = {
__index = {
disconnect = sysbench.sql.disconnect,
query = sysbench.sql.query,
bulk_insert_init = sysbench.sql.bulk_insert_init,
bulk_insert_next = sysbench.sql.bulk_insert_next,
bulk_insert_done = sysbench.sql.bulk_insert_done,
prepare = sysbench.sql.prepare,
},
__tostring = function() return '<sql_connection>' end,
__gc = ffi.C.db_connection_free,
}
ffi.metatype("struct db_conn", connection_mt)
-- sql_statement metatable
local statement_mt = {
__index = {
bind_param = sysbench.sql.bind_param,
},
__tostring = function() return '<sql_statement>' end,
__gc = ffi.C.db_close,
}
ffi.metatype("struct db_stmt", statement_mt)
-- sql_bind metatable
local bind_mt = {
__tostring = function() return '<sql_bind>' end,
}
ffi.metatype("sql_bind", bind_mt)
-- error codes
sysbench.sql.ERROR_NONE = ffi.C.DB_ERROR_NONE
sysbench.sql.ERROR_IGNORABLE = ffi.C.DB_ERROR_IGNORABLE
sysbench.sql.ERROR_FATAL = ffi.C.DB_ERROR_FATAL

View File

@ -24,10 +24,4 @@
#include "config.h"
#endif
#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT
# define SB_ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n)))
#else
# define SB_ATTRIBUTE_FORMAT(style, m, n)
#endif
#endif /* SB_GLOBAL_H */

View File

@ -27,7 +27,7 @@
# include <pthread.h>
#endif
#include "sb_global.h"
#include "sb_util.h"
#include "sb_options.h"
#include "sb_timer.h"
#include "sb_histogram.h"

View File

@ -1,5 +1,5 @@
/* Copyright (C) 2006 MySQL AB
Copyright (C) 2006-2016 Alexey Kopytov <akopytov@gmail.com>
Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
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
@ -32,6 +32,7 @@
#include "ck_pr.h"
/* Auto-generated headers */
#include "lua/internal/sysbench.lua.h"
#include "lua/internal/sysbench.sql.lua.h"
#define EVENT_FUNC "event"
#define PREPARE_FUNC "prepare"
@ -73,7 +74,7 @@ typedef struct {
} sb_lua_bind_t;
typedef struct {
db_result_set_t *ptr;
db_result_t *ptr;
} sb_lua_db_rs_t;
typedef struct {
@ -96,6 +97,8 @@ static unsigned int nevents;
static sb_test_t sbtest;
static const char *sb_lua_script_path;
/* Lua test operations */
static int sb_lua_op_init(void);
@ -116,26 +119,23 @@ static sb_operations_t lua_ops = {
static lua_State *gstate;
/* Database driver */
static db_driver_t *db_driver;
static TLS db_driver_t *db_driver;
/* Variable with unique address to store per-state data */
static const char sb_lua_ctxt_key = 0;
/* Control variable for sb_lua_db_init_once() */
static pthread_once_t db_init_control = PTHREAD_ONCE_INIT;
/* Lua test commands */
static int sb_lua_cmd_prepare(void);
static int sb_lua_cmd_cleanup(void);
static int sb_lua_cmd_help(void);
/* Initialize interpreter state */
static lua_State *sb_lua_new_state(const char *, int);
static lua_State *sb_lua_new_state(int);
/* Close interpretet state */
static int sb_lua_close_state(lua_State *);
/* Exported C functions */
/* Exported C functions for legacy Lua API */
static int sb_lua_db_connect(lua_State *);
static int sb_lua_db_disconnect(lua_State *);
static int sb_lua_db_query(lua_State *);
@ -165,14 +165,14 @@ unsigned int sb_lua_table_size(lua_State *, int);
sb_test_t *sb_load_lua(const char *testname)
{
unsigned int i;
#ifdef DATA_PATH
setenv("LUA_PATH", DATA_PATH LUA_DIRSEP "?.lua", 0);
#endif
sb_lua_script_path = testname;
/* Initialize global interpreter state */
gstate = sb_lua_new_state(testname, -1);
gstate = sb_lua_new_state(-1);
if (gstate == NULL)
goto error;
@ -193,13 +193,9 @@ sb_test_t *sb_load_lua(const char *testname)
/* Test operations */
sbtest.ops = lua_ops;
lua_getglobal(gstate, THREAD_INIT_FUNC);
if (!lua_isnil(gstate, -1))
sbtest.ops.thread_init = &sb_lua_op_thread_init;
sbtest.ops.thread_init = &sb_lua_op_thread_init;
lua_getglobal(gstate, THREAD_DONE_FUNC);
if (!lua_isnil(gstate, -1))
sbtest.ops.thread_done = &sb_lua_op_thread_done;
sbtest.ops.thread_done = &sb_lua_op_thread_done;
lua_getglobal(gstate, THREAD_RUN_FUNC);
if (!lua_isnil(gstate, -1))
@ -207,30 +203,20 @@ sb_test_t *sb_load_lua(const char *testname)
sbtest.ops.print_stats = &sb_lua_op_print_stats;
/* Initialize per-thread interpreters */
/* Allocate per-thread interpreters array */
states = (lua_State **)calloc(sb_globals.num_threads, sizeof(lua_State *));
if (states == NULL)
goto error;
for (i = 0; i < sb_globals.num_threads; i++)
{
states[i] = sb_lua_new_state(testname, i);
if (states[i] == NULL)
goto error;
}
return &sbtest;
error:
sb_lua_close_state(gstate);
if (states != NULL)
{
for (i = 0; i < sb_globals.num_threads; i++)
sb_lua_close_state(states[i]);
free(states);
}
return NULL;
}
@ -271,15 +257,24 @@ sb_event_t sb_lua_next_event(int thread_id)
int sb_lua_op_thread_init(int thread_id)
{
lua_State * const L = states[thread_id];
lua_State * L;
L = sb_lua_new_state(thread_id);
if (L == NULL)
return 1;
states[thread_id] = L;
lua_getglobal(L, THREAD_INIT_FUNC);
lua_pushnumber(L, thread_id);
if (lua_pcall(L, 1, 1, 0))
if (!lua_isnil(L, -1))
{
CALL_ERROR(L, THREAD_INIT_FUNC);
return 1;
lua_pushnumber(L, thread_id);
if (lua_pcall(L, 1, 1, 0))
{
CALL_ERROR(L, THREAD_INIT_FUNC);
return 1;
}
}
return 0;
@ -304,34 +299,35 @@ int sb_lua_op_thread_run(int thread_id)
int sb_lua_op_thread_done(int thread_id)
{
lua_State * const L = states[thread_id];
int rc = 0;
lua_getglobal(L, THREAD_DONE_FUNC);
lua_pushnumber(L, thread_id);
if (lua_pcall(L, 1, 1, 0))
if (!lua_isnil(L, -1))
{
CALL_ERROR(L, THREAD_DONE_FUNC);
return 1;
lua_pushnumber(L, thread_id);
if (lua_pcall(L, 1, 1, 0))
{
CALL_ERROR(L, THREAD_DONE_FUNC);
rc = 1;
}
}
return 0;
sb_lua_close_state(L);
return rc;
}
void sb_lua_op_print_stats(sb_stat_t type)
{
/* check if db driver has been initialized */
if (db_driver != NULL)
db_print_stats(type);
db_print_stats(type);
}
int sb_lua_op_done(void)
{
unsigned int i;
for (i = 0; i < sb_globals.num_threads; i++)
lua_close(states[i]);
free(states);
if (states != NULL)
free(states);
lua_getglobal(gstate, DONE_FUNC);
if (!lua_isnil(gstate, -1))
@ -348,7 +344,7 @@ int sb_lua_op_done(void)
/* Allocate and initialize new interpreter state */
lua_State *sb_lua_new_state(const char *scriptname, int thread_id)
lua_State *sb_lua_new_state(int thread_id)
{
lua_State *L;
sb_lua_ctxt_t *ctxt;
@ -447,9 +443,9 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id)
SB_LUA_FUNC("store_results", sb_lua_db_store_results);
SB_LUA_FUNC("free_results", sb_lua_db_free_results);
SB_LUA_VAR("DB_ERROR_NONE", SB_DB_ERROR_NONE);
SB_LUA_VAR("DB_ERROR_RESTART_TRANSACTION", SB_DB_ERROR_RESTART_TRANSACTION);
SB_LUA_VAR("DB_ERROR_FAILED", SB_DB_ERROR_FAILED);
SB_LUA_VAR("DB_ERROR_NONE", DB_ERROR_NONE);
SB_LUA_VAR("DB_ERROR_RESTART_TRANSACTION", DB_ERROR_IGNORABLE);
SB_LUA_VAR("DB_ERROR_FAILED", DB_ERROR_FATAL);
#undef SB_LUA_VAR
#undef SB_LUA_FUNC
@ -467,18 +463,36 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id)
{
log_text(LOG_FATAL, "failed to load internal module sysbench.lua: %s",
lua_tostring(L, -1));
return NULL;
}
lua_pushstring(L, "sysbench");
lua_call(L, 1, 0);
if (luaL_loadfile(L, scriptname))
if (luaL_loadbuffer(L, (const char *) sysbench_sql_lua, sysbench_sql_lua_len,
"sysbench.sql.lua"))
{
log_text(LOG_FATAL, "failed to load internal module sysbench.sql.lua: %s",
lua_tostring(L, -1));
return NULL;
}
lua_pushstring(L, "sysbench.sql");
lua_call(L, 1, 0);
int rc;
if ((rc = luaL_loadfile(L, sb_lua_script_path)))
{
if (rc != LUA_ERRFILE)
{
lua_error(L);
return NULL;
}
#ifdef DATA_PATH
/* first location failed - look in DATA_PATH */
char p[PATH_MAX + 1];
strncpy(p, DATA_PATH LUA_DIRSEP, sizeof(p));
strncat(p, scriptname, sizeof(p)-strlen(p)-1);
if (!strrchr(scriptname, '.'))
strncat(p, sb_lua_script_path, sizeof(p)-strlen(p)-1);
if (!strrchr(sb_lua_script_path, '.'))
{
/* add .lua extension if there isn't one */
strncat(p, ".lua", sizeof(p)-strlen(p)-1);
@ -490,6 +504,7 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id)
return NULL;
}
#else
lua_error(L);
return NULL;
#endif
}
@ -519,6 +534,12 @@ int sb_lua_close_state(lua_State *state)
if (state != NULL)
lua_close(state);
if (db_driver != NULL)
{
db_destroy(db_driver);
db_driver = NULL;
}
return 0;
}
@ -571,29 +592,19 @@ int sb_lua_cmd_help(void)
}
/* init_routine for pthread_once() */
static void sb_lua_db_init_once(void)
{
if (db_driver == NULL)
db_driver = db_init(NULL);
}
int sb_lua_db_connect(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
ctxt = sb_lua_get_context(L);
/* Initialize the DB driver once for all threads */
pthread_once(&db_init_control, sb_lua_db_init_once);
db_driver = db_create(NULL);
if (db_driver == NULL)
luaL_error(L, "DB initialization failed");
lua_pushstring(L, db_driver->sname);
lua_setglobal(L, "db_driver");
ctxt->con = db_connect(db_driver);
ctxt->con = db_connection_create(db_driver);
if (ctxt->con == NULL)
luaL_error(L, "Failed to connect to the database");
db_set_thread(ctxt->con, ctxt->thread_id);
@ -608,7 +619,10 @@ int sb_lua_db_disconnect(lua_State *L)
ctxt = sb_lua_get_context(L);
if (ctxt->con)
db_disconnect(ctxt->con);
{
db_connection_close(ctxt->con);
db_connection_free(ctxt->con);
}
ctxt->con = NULL;
@ -617,26 +631,26 @@ int sb_lua_db_disconnect(lua_State *L)
int sb_lua_db_query(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
const char *query;
db_result_set_t *rs;
sb_lua_ctxt_t *ctxt;
const char *query;
db_result_t *rs;
size_t len;
ctxt = sb_lua_get_context(L);
if (ctxt->con == NULL)
sb_lua_db_connect(L);
query = luaL_checkstring(L, 1);
rs = db_query(ctxt->con, query);
query = luaL_checklstring(L, 1, &len);
rs = db_query(ctxt->con, query, len);
if (rs == NULL)
{
lua_pushnumber(L, ctxt->con->db_errno);
lua_error(L);
}
db_store_results(rs);
db_free_results(rs);
return 0;
}
@ -644,16 +658,17 @@ int sb_lua_db_bulk_insert_init(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
const char *query;
size_t len;
ctxt = sb_lua_get_context(L);
if (ctxt->con == NULL)
sb_lua_db_connect(L);
query = luaL_checkstring(L, 1);
if (db_bulk_insert_init(ctxt->con, query))
query = luaL_checklstring(L, 1, &len);
if (db_bulk_insert_init(ctxt->con, query, len))
luaL_error(L, "db_bulk_insert_init() failed");
return 0;
}
@ -661,13 +676,14 @@ int sb_lua_db_bulk_insert_next(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
const char *query;
size_t len;
ctxt = sb_lua_get_context(L);
CHECK_CONNECTION(L, ctxt);
query = luaL_checkstring(L, 1);
if (db_bulk_insert_next(ctxt->con, query))
query = luaL_checklstring(L, 1, &len);
if (db_bulk_insert_next(ctxt->con, query, len))
luaL_error(L, "db_bulk_insert_next() failed");
return 0;
@ -688,23 +704,24 @@ int sb_lua_db_bulk_insert_done(lua_State *L)
int sb_lua_db_prepare(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
sb_lua_ctxt_t *ctxt;
sb_lua_db_stmt_t *stmt;
const char *query;
const char *query;
size_t len;
ctxt = sb_lua_get_context(L);
if (ctxt->con == NULL)
sb_lua_db_connect(L);
query = luaL_checkstring(L, 1);
query = luaL_checklstring(L, 1, &len);
stmt = (sb_lua_db_stmt_t *)lua_newuserdata(L, sizeof(sb_lua_db_stmt_t));
luaL_getmetatable(L, "sysbench.stmt");
lua_setmetatable(L, -2);
memset(stmt, 0, sizeof(sb_lua_db_stmt_t));
stmt->ptr = db_prepare(ctxt->con, query);
stmt->ptr = db_prepare(ctxt->con, query, len);
if (stmt->ptr == NULL)
luaL_error(L, "db_prepare() failed");
@ -866,7 +883,7 @@ int sb_lua_db_execute(lua_State *L)
{
sb_lua_ctxt_t *ctxt;
sb_lua_db_stmt_t *stmt;
db_result_set_t *ptr;
db_result_t *ptr;
sb_lua_db_rs_t *rs;
unsigned int i;
char needs_rebind = 0;
@ -1014,8 +1031,8 @@ int sb_lua_db_store_results(lua_State *L)
rs = (sb_lua_db_rs_t *)luaL_checkudata(L, 1, "sysbench.rs");
luaL_argcheck(L, rs != NULL, 1, "result set expected");
db_store_results(rs->ptr);
/* noop as db_store_results() is now performed automatically by db_query() */
return 0;
}

View File

@ -30,6 +30,7 @@
#include "sb_logger.h"
#include "sb_timer.h"
#include "sb_util.h"
/* Some functions for simple time operations */
@ -37,6 +38,8 @@
void sb_timer_init(sb_timer_t *t)
{
SB_COMPILE_TIME_ASSERT(sizeof(sb_timer_t) % CK_MD_CACHELINE == 0);
memset(&t->time_start, 0, sizeof(struct timespec));
memset(&t->time_end, 0, sizeof(struct timespec));
sb_timer_reset(t);

View File

@ -114,9 +114,9 @@ static inline uint64_t sb_timer_stop(sb_timer_t *t)
t->events++;
t->sum_time += elapsed;
if (CK_CC_UNLIKELY(elapsed < t->min_time))
if (SB_UNLIKELY(elapsed < t->min_time))
t->min_time = elapsed;
if (CK_CC_UNLIKELY(elapsed > t->max_time))
if (SB_UNLIKELY(elapsed > t->max_time))
t->max_time = elapsed;
return elapsed;

View File

@ -30,6 +30,18 @@
#include "ck_md.h"
#include "ck_cc.h"
#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT
# define SB_ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n)))
#else
# define SB_ATTRIBUTE_FORMAT(style, m, n)
#endif
#ifdef HAVE_FUNC_ATTRIBUTE_UNUSED
# define SB_ATTRIBUTE_UNUSED __attribute__((unused))
#else
# define SB_ATTRIBUTE_UNUSED
#endif
/*
Calculate the smallest multiple of m that is not smaller than n, when m is a
power of 2.
@ -43,7 +55,7 @@
#define SB_PAD(n, m) (SB_ALIGN((n),(m)) - (n))
/* Calculate padding to cache line size. */
#define SB_CACHELINE_PAD(n) (SB_PAD(n, CK_MD_CACHELINE))
#define SB_CACHELINE_PAD(n) (SB_PAD((n), CK_MD_CACHELINE))
/* Minimum/maximum values */
#ifdef __GNUC__
@ -63,4 +75,20 @@
#define SB_LIKELY(x) CK_CC_LIKELY(x)
#define SB_UNLIKELY(x) CK_CC_UNLIKELY(x)
/* SB_CONTAINER_OF */
#ifdef __GNUC__
# define SB_MEMBER_TYPE(type, member) __typeof__ (((type *)0)->member)
#else
# define SB_MEMBER_TYPE(type, member) const void
#endif /* __GNUC__ */
#define SB_CONTAINER_OF(ptr, type, member) ((type *)(void *)( \
(char *)(SB_MEMBER_TYPE(type, member) *){ ptr } - offsetof(type, member)))
/* Compile-timer assertion */
#define SB_COMPILE_TIME_ASSERT(expr) \
do { \
typedef char cta[(expr) ? 1 : -1] SB_ATTRIBUTE_UNUSED; \
} while(0)
#endif /* SB_UTIL_H */

View File

@ -163,6 +163,8 @@ sb_timer_t sb_intermediate_timer CK_CC_CACHELINE;
sb_timer_t sb_checkpoint_timer1 CK_CC_CACHELINE;
sb_timer_t sb_checkpoint_timer2 CK_CC_CACHELINE;
TLS int sb_tls_thread_id;
static void print_header(void);
static void print_help(void);
static void print_run_mode(sb_test_t *);
@ -509,18 +511,21 @@ void sb_event_stop(int thread_id)
if (sb_globals.percentile > 0)
sb_histogram_update(&sb_latency_histogram, NS2MS(value));
db_thread_stat_inc(thread_id, DB_STAT_TRX);
}
/* Main event loop -- the default thread_run implementation */
static void thread_run(sb_test_t *test, int thread_id)
static int thread_run(sb_test_t *test, int thread_id)
{
sb_event_t event;
int rc;
int rc = 0;
while ((event = sb_next_event(test, thread_id)).type != SB_REQ_TYPE_NULL)
while ((event = sb_next_event(test, thread_id)).type != SB_REQ_TYPE_NULL &&
rc == 0)
{
sb_event_start(thread_id);
@ -534,10 +539,9 @@ static void thread_run(sb_test_t *test, int thread_id)
sb_globals.concurrency--;
pthread_mutex_unlock(&event_queue_mutex);
}
if (rc != 0)
break;
}
return rc;
}
@ -549,10 +553,12 @@ static void *worker_thread(void *arg)
sb_thread_ctxt_t *ctxt;
sb_test_t *test;
unsigned int thread_id;
int rc;
ctxt = (sb_thread_ctxt_t *)arg;
test = ctxt->test;
thread_id = ctxt->id;
sb_tls_thread_id = thread_id = ctxt->id;
/* Initialize thread-local RNG state */
sb_rand_thread_init();
@ -577,15 +583,17 @@ static void *worker_thread(void *arg)
if (test->ops.thread_run != NULL)
{
/* Use benchmark-provided thread_run implementation */
test->ops.thread_run(thread_id);
rc = test->ops.thread_run(thread_id);
}
else
{
/* Use default thread_run implementation */
thread_run(test, thread_id);
rc = thread_run(test, thread_id);
}
if (test->ops.thread_done != NULL)
if (rc != 0)
sb_globals.error = 1;
else if (test->ops.thread_done != NULL)
test->ops.thread_done(thread_id);
return NULL;
@ -779,6 +787,8 @@ static int threads_started_callback(void *arg)
sb_timer_copy(&sb_checkpoint_timer1, &sb_exec_timer);
sb_timer_copy(&sb_checkpoint_timer2, &sb_exec_timer);
log_text(LOG_NOTICE, "Threads started!\n");
return 0;
}
@ -928,8 +938,6 @@ static int run_test(sb_test_t *test)
}
#endif
log_text(LOG_NOTICE, "Threads started!\n");
for(i = 0; i < sb_globals.num_threads; i++)
{
if((err = sb_thread_join(threads[i].thread, NULL)) != 0)
@ -1177,9 +1185,9 @@ int main(int argc, char *argv[])
}
/* Initialize global variables and logger */
if (init() || log_init())
if (init() || log_init() || db_thread_stat_init())
exit(1);
print_header();
testname = sb_get_value_string("test");
@ -1254,7 +1262,8 @@ int main(int argc, char *argv[])
if (run_test(test))
exit(1);
/* Uninitialize logger */
db_done();
log_done();
sb_options_done();

View File

@ -218,6 +218,8 @@ extern sb_timer_t sb_intermediate_timer;
extern sb_timer_t sb_checkpoint_timer1;
extern sb_timer_t sb_checkpoint_timer2;
extern TLS int sb_tls_thread_id;
sb_event_t sb_next_event(sb_test_t *test, int thread_id);
void sb_event_start(int thread_id);
void sb_event_stop(int thread_id);

View File

@ -15,9 +15,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
dist_pkgdata_DATA = common.lua delete.lua insert.lua bulk_insert.lua \
oltp.lua \
oltp_simple.lua \
dist_pkgdata_DATA = delete.lua insert.lua bulk_insert.lua \
oltp_read_write.lua oltp_read_only.lua \
oltp_common.lua \
oltp_point_select.lua \
parallel_prepare.lua \
select_random_points.lua \
select_random_ranges.lua \

View File

@ -1,61 +0,0 @@
-- -------------------------------------------------------------------------- --
-- Bulk insert tests --
-- -------------------------------------------------------------------------- --
cursize=0
function prepare()
local i
db_connect()
for i = 0,num_threads-1 do
if (db_driver == "pgsql") then
db_query([[
CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ (
id INTEGER NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
PRIMARY KEY (id)
)]])
else
db_query([[
CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (id)
) ENGINE = InnoDB
]])
end
end --for
end
function event()
local i
if (cursize == 0) then
db_bulk_insert_init("INSERT INTO sbtest" .. thread_id .. " VALUES")
end
cursize = cursize + 1
db_bulk_insert_next("(" .. cursize .. "," .. cursize .. ")")
end
function thread_done(thread_9d)
db_bulk_insert_done()
end
function cleanup()
local i
for i = 0,num_threads-1 do
print("Dropping table 'sbtest" .. i .. "'...")
db_query("DROP TABLE IF EXISTS sbtest".. i )
end
end

View File

@ -1,17 +0,0 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -1,42 +0,0 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init(thread_id)
set_vars()
end
function event()
local table_name
local i
local c_val
local k_val
local pad_val
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
k_val = sb_rand(1, oltp_table_size)
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
if (db_driver == "pgsql" and oltp_auto_inc) then
rs = db_query("INSERT INTO " .. table_name .. " (k, c, pad) VALUES " ..
string.format("(%d, '%s', '%s')", k_val, c_val, pad_val))
else
if (oltp_auto_inc) then
i = 0
else
i = sb_rand_uniq()
end
rs = db_query("INSERT INTO " .. table_name ..
" (id, k, c, pad) VALUES " ..
string.format("(%d, %d, '%s', '%s')", i, k_val, c_val,
pad_val))
end
end

View File

@ -0,0 +1,204 @@
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- 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; either version 2 of the License, or
-- (at your option) any later version.
-- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- Common code for OLTP benchmarks
-- ----------------------------------------------------------------------
function create_insert(table_id)
local index_name
local i
local j
local query
if (oltp_secondary) then
index_name = "KEY xid"
else
index_name = "PRIMARY KEY"
end
if (pgsql_variant == 'redshift') then
auto_inc_type = "INTEGER IDENTITY(1,1)"
else
auto_inc_type = "SERIAL"
end
i = table_id
print("Creating table 'sbtest" .. i .. "'...")
if ((db_driver == "mysql") or (db_driver == "attachsql")) then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL ]] ..
((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) /*! ENGINE = ]] .. mysql_table_engine ..
" MAX_ROWS = " .. myisam_max_rows .. " */ " ..
(mysql_table_options or "")
elseif (db_driver == "pgsql") then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id ]] .. auto_inc_type .. [[ NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
elseif (db_driver == "drizzle") then
query = [[
CREATE TABLE sbtest (
id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
else
print("Unknown database driver: " .. db_driver)
return 1
end
db_query(query)
print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'")
if (oltp_auto_inc) then
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES")
else
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES")
end
local c_val
local pad_val
for j = 1,oltp_table_size do
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
if (oltp_auto_inc) then
db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')")
else
db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "' )")
end
end
db_bulk_insert_done()
if oltp_create_secondary then
print("Creating secondary indexes on 'sbtest" .. i .. "'...")
db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)")
end
end
function prepare()
local query
local i
local j
set_vars()
db_connect()
for i = 1,oltp_tables_count do
create_insert(i)
end
return 0
end
function cleanup()
local i
set_vars()
for i = 1,oltp_tables_count do
print("Dropping table 'sbtest" .. i .. "'...")
db_query("DROP TABLE IF EXISTS sbtest".. i )
end
end
function set_vars()
oltp_table_size = tonumber(oltp_table_size) or 10000
oltp_range_size = tonumber(oltp_range_size) or 100
oltp_tables_count = tonumber(oltp_tables_count) or 1
oltp_point_selects = tonumber(oltp_point_selects) or 10
oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1
oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1
oltp_order_ranges = tonumber(oltp_order_ranges) or 1
oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1
oltp_index_updates = tonumber(oltp_index_updates) or 1
oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1
oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1
if (oltp_range_selects == 'off') then
oltp_range_selects = false
else
oltp_range_selects = true
end
if (oltp_auto_inc == 'off') then
oltp_auto_inc = false
else
oltp_auto_inc = true
end
if (oltp_read_only == 'on') then
oltp_read_only = true
else
oltp_read_only = false
end
if (oltp_write_only == 'on') then
oltp_write_only = true
else
oltp_write_only = false
end
if (oltp_read_only and oltp_write_only) then
error("--oltp-read-only and --oltp-write-only are mutually exclusive")
end
if (oltp_skip_trx == 'on') then
oltp_skip_trx = true
else
oltp_skip_trx = false
end
if (oltp_create_secondary == 'off') then
oltp_create_secondary = false
else
oltp_create_secondary = true
end
if (pgsql_variant == 'redshift') then
oltp_create_secondary = false
oltp_delete_inserts = 0
end
end

View File

@ -0,0 +1,39 @@
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
-- 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; either version 2 of the License, or
-- (at your option) any later version.
-- 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-- ----------------------------------------------------------------------
-- OLTP Point Select benchmark
-- ----------------------------------------------------------------------
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "oltp_common.lua")
else
require("oltp_common")
end
function thread_init()
set_vars()
drv = sysbench.sql.driver()
con = drv:connect()
end
function event()
con:query(string.format("SELECT c FROM sbtest%d WHERE id=%d",
sysbench.rand.uniform(1, oltp_tables_count),
sysbench.rand.default(1, oltp_table_size)))
end

View File

View File

View File

@ -1,30 +0,0 @@
-- for proper initialization use --max-requests = N, where N is --num-threads
--
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local index_name
local i
print("thread prepare"..thread_id)
if (oltp_secondary) then
index_name = "KEY xid"
else
index_name = "PRIMARY KEY"
end
for i=thread_id+1, oltp_tables_count, num_threads do
create_insert(i)
end
end

View File

@ -1,18 +0,0 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("SELECT pad FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -1,61 +0,0 @@
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
-- Override oltp_tables_count, this test only supports a single table
oltp_tables_count = 1
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars_points()
points = ""
for i = 1,random_points do
points = points .. "?, "
end
-- Get rid of last comma and space.
points = string.sub(points, 1, string.len(points) - 2)
stmt = db_prepare([[
SELECT id, k, c, pad
FROM sbtest1
WHERE k IN (]] .. points .. [[)
]])
params = {}
for j = 1,random_points do
params[j] = 1
end
db_bind_param(stmt, params)
end
function event()
local rs
-- To prevent overlapping of our range queries we need to partition the whole table
-- into num_threads segments and then make each thread work with its own segment.
for i = 1,random_points do
params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1))
end
rs = db_execute(stmt)
db_store_results(rs)
db_free_results(rs)
end
function set_vars_points()
set_vars()
random_points = random_points or 10
end

View File

@ -1,64 +0,0 @@
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
-- Override oltp_tables_count, this test only supports a single table
oltp_tables_count = 1
function thread_init()
set_vars_ranges()
ranges = ""
for i = 1,number_of_ranges do
ranges = ranges .. "k BETWEEN ? AND ? OR "
end
-- Get rid of last OR and space.
ranges = string.sub(ranges, 1, string.len(ranges) - 3)
stmt = db_prepare([[
SELECT count(k)
FROM sbtest1
WHERE ]] .. ranges .. [[
]])
params = {}
for j = 1,number_of_ranges * 2 do
params[j] = 1
end
db_bind_param(stmt, params)
end
function event()
local rs
-- To prevent overlapping of our range queries we need to partition the whole table
-- into num_threads segments and then make each thread work with its own segment.
for i = 1,number_of_ranges * 2,2 do
params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1))
params[i + 1] = params[i] + delta
end
rs = db_execute(stmt)
db_store_results(rs)
db_free_results(rs)
end
function set_vars_ranges()
set_vars()
number_of_ranges = number_of_ranges or 10
delta = random_ranges_delta or 5
end

View File

@ -1,17 +0,0 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("UPDATE ".. table_name .." SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -1,21 +0,0 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
local c_val
local query
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########")
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
rs = db_query(query)
end

View File

@ -76,6 +76,8 @@ static unsigned int mutex_loops;
static unsigned int mutex_locks;
static unsigned int global_var;
static TLS int tls_counter;
int register_test_mutex(sb_list_t *tests)
{
SB_LIST_ADD_TAIL(&mutex_test.listitem, tests);
@ -125,9 +127,15 @@ sb_event_t mutex_next_event(int thread_id)
(void) thread_id; /* unused */
sb_req.type = SB_REQ_TYPE_MUTEX;
mutex_req->nlocks = mutex_locks;
mutex_req->nloops = mutex_loops;
/* Perform only one request per thread */
if (tls_counter++ > 0)
sb_req.type = SB_REQ_TYPE_NULL;
else
{
sb_req.type = SB_REQ_TYPE_MUTEX;
mutex_req->nlocks = mutex_locks;
mutex_req->nloops = mutex_loops;
}
return sb_req;
}
@ -154,8 +162,7 @@ int mutex_execute_event(sb_event_t *sb_req, int thread_id)
}
while (mutex_req->nlocks > 0);
/* Perform only one request per thread */
return 1;
return 0;
}

View File

@ -0,0 +1,61 @@
-- -------------------------------------------------------------------------- --
-- Bulk insert tests --
-- -------------------------------------------------------------------------- --
cursize=0
function prepare()
local i
db_connect()
for i = 0,num_threads-1 do
if (db_driver == "pgsql") then
db_query([[
CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ (
id INTEGER NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
PRIMARY KEY (id)
)]])
else
db_query([[
CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (id)
) ENGINE = InnoDB
]])
end
end --for
end
function event()
local i
if (cursize == 0) then
db_bulk_insert_init("INSERT INTO sbtest" .. thread_id .. " VALUES")
end
cursize = cursize + 1
db_bulk_insert_next("(" .. cursize .. "," .. cursize .. ")")
end
function thread_done(thread_9d)
db_bulk_insert_done()
end
function cleanup()
local i
for i = 0,num_threads-1 do
print("Dropping table 'sbtest" .. i .. "'...")
db_query("DROP TABLE IF EXISTS sbtest".. i )
end
end

View File

@ -0,0 +1,190 @@
-- Input parameters
-- oltp-tables-count - number of tables to create
-- oltp-secondary - use secondary key instead PRIMARY key for id column
--
--
function create_insert(table_id)
local index_name
local i
local j
local query
if (oltp_secondary) then
index_name = "KEY xid"
else
index_name = "PRIMARY KEY"
end
if (pgsql_variant == 'redshift') then
auto_inc_type = "INTEGER IDENTITY(1,1)"
else
auto_inc_type = "SERIAL"
end
i = table_id
print("Creating table 'sbtest" .. i .. "'...")
if ((db_driver == "mysql") or (db_driver == "attachsql")) then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL ]] ..
((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) /*! ENGINE = ]] .. mysql_table_engine ..
" MAX_ROWS = " .. myisam_max_rows .. " */ " ..
(mysql_table_options or "")
elseif (db_driver == "pgsql") then
query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id ]] .. auto_inc_type .. [[ NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
elseif (db_driver == "drizzle") then
query = [[
CREATE TABLE sbtest (
id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
else
print("Unknown database driver: " .. db_driver)
return 1
end
db_query(query)
print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'")
if (oltp_auto_inc) then
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES")
else
db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES")
end
local c_val
local pad_val
for j = 1,oltp_table_size do
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
if (oltp_auto_inc) then
db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')")
else
db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "' )")
end
end
db_bulk_insert_done()
if oltp_create_secondary then
print("Creating secondary indexes on 'sbtest" .. i .. "'...")
db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)")
end
end
function prepare()
local query
local i
local j
set_vars()
db_connect()
for i = 1,oltp_tables_count do
create_insert(i)
end
return 0
end
function cleanup()
local i
set_vars()
for i = 1,oltp_tables_count do
print("Dropping table 'sbtest" .. i .. "'...")
db_query("DROP TABLE IF EXISTS sbtest".. i )
end
end
function set_vars()
oltp_table_size = tonumber(oltp_table_size) or 10000
oltp_range_size = tonumber(oltp_range_size) or 100
oltp_tables_count = tonumber(oltp_tables_count) or 1
oltp_point_selects = tonumber(oltp_point_selects) or 10
oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1
oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1
oltp_order_ranges = tonumber(oltp_order_ranges) or 1
oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1
oltp_index_updates = tonumber(oltp_index_updates) or 1
oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1
oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1
if (oltp_range_selects == 'off') then
oltp_range_selects = false
else
oltp_range_selects = true
end
if (oltp_auto_inc == 'off') then
oltp_auto_inc = false
else
oltp_auto_inc = true
end
if (oltp_read_only == 'on') then
oltp_read_only = true
else
oltp_read_only = false
end
if (oltp_write_only == 'on') then
oltp_write_only = true
else
oltp_write_only = false
end
if (oltp_read_only and oltp_write_only) then
error("--oltp-read-only and --oltp-write-only are mutually exclusive")
end
if (oltp_skip_trx == 'on') then
oltp_skip_trx = true
else
oltp_skip_trx = false
end
if (oltp_create_secondary == 'off') then
oltp_create_secondary = false
else
oltp_create_secondary = true
end
if (pgsql_variant == 'redshift') then
oltp_create_secondary = false
oltp_delete_inserts = 0
end
end

View File

@ -0,0 +1,17 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -0,0 +1,42 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init(thread_id)
set_vars()
end
function event()
local table_name
local i
local c_val
local k_val
local pad_val
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
k_val = sb_rand(1, oltp_table_size)
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
if (db_driver == "pgsql" and oltp_auto_inc) then
rs = db_query("INSERT INTO " .. table_name .. " (k, c, pad) VALUES " ..
string.format("(%d, '%s', '%s')", k_val, c_val, pad_val))
else
if (oltp_auto_inc) then
i = 0
else
i = sb_rand_uniq()
end
rs = db_query("INSERT INTO " .. table_name ..
" (id, k, c, pad) VALUES " ..
string.format("(%d, %d, '%s', '%s')", i, k_val, c_val,
pad_val))
end
end

View File

@ -0,0 +1,114 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
if (((db_driver == "mysql") or (db_driver == "attachsql")) and mysql_table_engine == "myisam") then
local i
local tables = {}
for i=1, oltp_tables_count do
tables[i] = string.format("sbtest%i WRITE", i)
end
begin_query = "LOCK TABLES " .. table.concat(tables, " ,")
commit_query = "UNLOCK TABLES"
else
begin_query = "BEGIN"
commit_query = "COMMIT"
end
end
function get_range_str()
local start = sb_rand(1, oltp_table_size)
return string.format(" WHERE id BETWEEN %u AND %u",
start, start + oltp_range_size - 1)
end
function event()
local rs
local i
local table_name
local c_val
local pad_val
local query
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
if not oltp_skip_trx then
db_query(begin_query)
end
if not oltp_write_only then
for i=1, oltp_point_selects do
rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" ..
sb_rand(1, oltp_table_size))
end
if oltp_range_selects then
for i=1, oltp_simple_ranges do
rs = db_query("SELECT c FROM ".. table_name .. get_range_str())
end
for i=1, oltp_sum_ranges do
rs = db_query("SELECT SUM(K) FROM ".. table_name .. get_range_str())
end
for i=1, oltp_order_ranges do
rs = db_query("SELECT c FROM ".. table_name .. get_range_str() ..
" ORDER BY c")
end
for i=1, oltp_distinct_ranges do
rs = db_query("SELECT DISTINCT c FROM ".. table_name .. get_range_str() ..
" ORDER BY c")
end
end
end
if not oltp_read_only then
for i=1, oltp_index_updates do
rs = db_query("UPDATE " .. table_name .. " SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
end
for i=1, oltp_non_index_updates do
c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########")
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
rs = db_query(query)
if rs then
print(query)
end
end
for i=1, oltp_delete_inserts do
i = sb_rand(1, oltp_table_size)
rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i)
c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])
rs = db_query("INSERT INTO " .. table_name .. " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val))
end
end -- oltp_read_only
if not oltp_skip_trx then
db_query(commit_query)
end
end

View File

@ -0,0 +1,30 @@
-- for proper initialization use --max-requests = N, where N is --num-threads
--
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local index_name
local i
print("thread prepare"..thread_id)
if (oltp_secondary) then
index_name = "KEY xid"
else
index_name = "PRIMARY KEY"
end
for i=thread_id+1, oltp_tables_count, num_threads do
create_insert(i)
end
end

View File

@ -0,0 +1,18 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("SELECT pad FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -0,0 +1,61 @@
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
-- Override oltp_tables_count, this test only supports a single table
oltp_tables_count = 1
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars_points()
points = ""
for i = 1,random_points do
points = points .. "?, "
end
-- Get rid of last comma and space.
points = string.sub(points, 1, string.len(points) - 2)
stmt = db_prepare([[
SELECT id, k, c, pad
FROM sbtest1
WHERE k IN (]] .. points .. [[)
]])
params = {}
for j = 1,random_points do
params[j] = 1
end
db_bind_param(stmt, params)
end
function event()
local rs
-- To prevent overlapping of our range queries we need to partition the whole table
-- into num_threads segments and then make each thread work with its own segment.
for i = 1,random_points do
params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1))
end
rs = db_execute(stmt)
db_store_results(rs)
db_free_results(rs)
end
function set_vars_points()
set_vars()
random_points = random_points or 10
end

View File

@ -0,0 +1,64 @@
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
-- and should work with other storage engines as well.
--
-- For details about key_cache_segments please refer to:
-- http://kb.askmonty.org/v/segmented-key-cache
--
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
-- Override oltp_tables_count, this test only supports a single table
oltp_tables_count = 1
function thread_init()
set_vars_ranges()
ranges = ""
for i = 1,number_of_ranges do
ranges = ranges .. "k BETWEEN ? AND ? OR "
end
-- Get rid of last OR and space.
ranges = string.sub(ranges, 1, string.len(ranges) - 3)
stmt = db_prepare([[
SELECT count(k)
FROM sbtest1
WHERE ]] .. ranges .. [[
]])
params = {}
for j = 1,number_of_ranges * 2 do
params[j] = 1
end
db_bind_param(stmt, params)
end
function event()
local rs
-- To prevent overlapping of our range queries we need to partition the whole table
-- into num_threads segments and then make each thread work with its own segment.
for i = 1,number_of_ranges * 2,2 do
params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1))
params[i + 1] = params[i] + delta
end
rs = db_execute(stmt)
db_store_results(rs)
db_free_results(rs)
end
function set_vars_ranges()
set_vars()
number_of_ranges = number_of_ranges or 10
delta = random_ranges_delta or 5
end

View File

@ -0,0 +1,17 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
rs = db_query("UPDATE ".. table_name .." SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
end

View File

@ -0,0 +1,21 @@
pathtest = string.match(test, "(.*/)")
if pathtest then
dofile(pathtest .. "common.lua")
else
require("common")
end
function thread_init()
set_vars()
end
function event()
local table_name
local c_val
local query
table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)
c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########")
query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
rs = db_query(query)
end

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
################################################################################
# Common code for OLTP tests
# Common code for legacy OLTP tests
#
# Expects the following variables and callback functions to be defined by the
# caller:
@ -14,7 +14,7 @@
set -eu
ARGS="--test=${SBTEST_SCRIPTDIR}/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8"
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8"
sysbench $ARGS prepare
@ -42,7 +42,7 @@ db_show_table sbtest7 || true # Error on non-existing table
db_show_table sbtest8 || true # Error on non-existing table
# Test --oltp-create-secondary=off
ARGS="--test=${SBTEST_SCRIPTDIR}/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1"
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1"
sysbench $ARGS --oltp-create-secondary=off prepare

View File

@ -0,0 +1,51 @@
#!/usr/bin/env bash
#
################################################################################
# Common code for legacy OLTP tests
#
# Expects the following variables and callback functions to be defined by the
# caller:
#
# DB_DRIVER_ARGS -- extra driver-specific arguments to pass to sysbench
#
# db_show_table() -- called with a single argument to dump a specified table
# schema
################################################################################
set -eu
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8"
sysbench $ARGS prepare
db_show_table sbtest1
db_show_table sbtest2
db_show_table sbtest3
db_show_table sbtest4
db_show_table sbtest5
db_show_table sbtest6
db_show_table sbtest7
db_show_table sbtest8
db_show_table sbtest9 || true # Error on non-existing table
sysbench $ARGS --max-requests=100 --num-threads=2 run
sysbench $ARGS cleanup
db_show_table sbtest1 || true # Error on non-existing table
db_show_table sbtest2 || true # Error on non-existing table
db_show_table sbtest3 || true # Error on non-existing table
db_show_table sbtest4 || true # Error on non-existing table
db_show_table sbtest5 || true # Error on non-existing table
db_show_table sbtest6 || true # Error on non-existing table
db_show_table sbtest7 || true # Error on non-existing table
db_show_table sbtest8 || true # Error on non-existing table
# Test --oltp-create-secondary=off
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1"
sysbench $ARGS --oltp-create-secondary=off prepare
db_show_table sbtest1
sysbench $ARGS cleanup

View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
#
################################################################################
# Common code for select_random_* tests
#
# Expects the following variables and callback functions to be defined by the
# caller:
#
# DB_DRIVER_ARGS -- extra driver-specific arguments to pass to sysbench
#
# db_show_table() -- called with a single argument to dump a specified table
# schema
################################################################################
set -eu
for test in select_random_points select_random_ranges
do
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/${test}.lua $DB_DRIVER_ARGS --oltp-tables-count=8"
sysbench $ARGS prepare
db_show_table sbtest1
for i in $(seq 2 8)
do
db_show_table sbtest${i} || true # Error on non-existing table
done
sysbench $ARGS --max-requests=100 --num-threads=1 run
sysbench $ARGS cleanup
for i in $(seq 1 8)
do
db_show_table sbtest${i} || true # Error on non-existing table
done
ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/select_random_points.lua $DB_DRIVER_ARGS --oltp-tables-count=8"
done

View File

@ -1,5 +1,5 @@
########################################################################
Basic Lua API tests
Legacy basic Lua API tests
########################################################################
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]

View File

@ -1,5 +1,5 @@
########################################################################
PRNG Lua API tests
Legacy PRNG Lua API tests
########################################################################
$ SB_ARGS="--verbosity=0 --test=$CRAMTMP/api_legacy_rand.lua --max-requests=1 --num-threads=1"

View File

@ -1,5 +1,5 @@
########################################################################
SQL Lua API tests
Legacy SQL Lua API tests
########################################################################
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
@ -40,9 +40,9 @@ SQL Lua API tests
$ mysql -uroot sbtest -Nse "DROP TABLE IF EXISTS t"
$ sysbench $SB_ARGS run
DB_ERROR_NONE = 0
DB_ERROR_RESTART_TRANSACTION = 1
DB_ERROR_FAILED = 3
DB_ERROR_NONE = [0-9] (re)
DB_ERROR_RESTART_TRANSACTION = [0-9] (re)
DB_ERROR_FAILED = [0-9] (re)
$ mysql -uroot sbtest -Nse "SHOW CREATE TABLE t\G"
*************************** 1. row ***************************
@ -60,3 +60,370 @@ SQL Lua API tests
200
$ mysql -uroot sbtest -Nse "DROP TABLE t"
$ function db_show_table() {
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
> }
$ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=myisam $SBTEST_MYSQL_ARGS"
$ . $SBTEST_INCDIR/script_oltp_legacy_common.sh
sysbench *.* * (glob)
Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
Creating secondary indexes on 'sbtest1'...
Creating table 'sbtest2'...
Inserting 10000 records into 'sbtest2'
Creating secondary indexes on 'sbtest2'...
Creating table 'sbtest3'...
Inserting 10000 records into 'sbtest3'
Creating secondary indexes on 'sbtest3'...
Creating table 'sbtest4'...
Inserting 10000 records into 'sbtest4'
Creating secondary indexes on 'sbtest4'...
Creating table 'sbtest5'...
Inserting 10000 records into 'sbtest5'
Creating secondary indexes on 'sbtest5'...
Creating table 'sbtest6'...
Inserting 10000 records into 'sbtest6'
Creating secondary indexes on 'sbtest6'...
Creating table 'sbtest7'...
Inserting 10000 records into 'sbtest7'
Creating secondary indexes on 'sbtest7'...
Creating table 'sbtest8'...
Inserting 10000 records into 'sbtest8'
Creating secondary indexes on 'sbtest8'...
*************************** 1. row ***************************
sbtest1
CREATE TABLE `sbtest1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest2
CREATE TABLE `sbtest2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_2` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest3
CREATE TABLE `sbtest3` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_3` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest4
CREATE TABLE `sbtest4` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_4` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest5
CREATE TABLE `sbtest5` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_5` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest6
CREATE TABLE `sbtest6` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_6` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest7
CREATE TABLE `sbtest7` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_7` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest8
CREATE TABLE `sbtest8` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_8` (`k`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest9' doesn't exist
sysbench *.* * (glob)
Running the test with following options:
Number of threads: 2
Initializing random number generator from current time
Initializing worker threads...
Threads started!
OLTP test statistics:
queries performed:
read: 1400
write: 400
other: 200
total: 2000
transactions: 100 (* per sec.) (glob)
queries: 2000 (* per sec.) (glob)
ignored errors: 0 (* per sec.) (glob)
reconnects: 0 (* per sec.) (glob)
General statistics:
total time: *s (glob)
total number of events: 100
total time taken by event execution: *s (glob)
Latency statistics:
min: *.*ms (glob)
avg: *.*ms (glob)
max: *.*ms (glob)
approx. 95th percentile: *.*ms (glob)
Threads fairness:
events (avg/stddev): */* (glob)
execution time (avg/stddev): */* (glob)
sysbench *.* * (glob)
Dropping table 'sbtest1'...
Dropping table 'sbtest2'...
Dropping table 'sbtest3'...
Dropping table 'sbtest4'...
Dropping table 'sbtest5'...
Dropping table 'sbtest6'...
Dropping table 'sbtest7'...
Dropping table 'sbtest8'...
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest1' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest2' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest3' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest4' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest5' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest6' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest7' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest8' doesn't exist
sysbench * (glob)
Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
*************************** 1. row ***************************
sbtest1
CREATE TABLE `sbtest1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
sysbench * (glob)
Dropping table 'sbtest1'...
$ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=innodb $SBTEST_MYSQL_ARGS"
$ . $SBTEST_INCDIR/script_oltp_legacy_common.sh
sysbench *.* * (glob)
Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
Creating secondary indexes on 'sbtest1'...
Creating table 'sbtest2'...
Inserting 10000 records into 'sbtest2'
Creating secondary indexes on 'sbtest2'...
Creating table 'sbtest3'...
Inserting 10000 records into 'sbtest3'
Creating secondary indexes on 'sbtest3'...
Creating table 'sbtest4'...
Inserting 10000 records into 'sbtest4'
Creating secondary indexes on 'sbtest4'...
Creating table 'sbtest5'...
Inserting 10000 records into 'sbtest5'
Creating secondary indexes on 'sbtest5'...
Creating table 'sbtest6'...
Inserting 10000 records into 'sbtest6'
Creating secondary indexes on 'sbtest6'...
Creating table 'sbtest7'...
Inserting 10000 records into 'sbtest7'
Creating secondary indexes on 'sbtest7'...
Creating table 'sbtest8'...
Inserting 10000 records into 'sbtest8'
Creating secondary indexes on 'sbtest8'...
*************************** 1. row ***************************
sbtest1
CREATE TABLE `sbtest1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest2
CREATE TABLE `sbtest2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_2` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest3
CREATE TABLE `sbtest3` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_3` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest4
CREATE TABLE `sbtest4` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_4` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest5
CREATE TABLE `sbtest5` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_5` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest6
CREATE TABLE `sbtest6` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_6` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest7
CREATE TABLE `sbtest7` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_7` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
*************************** 1. row ***************************
sbtest8
CREATE TABLE `sbtest8` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`),
KEY `k_8` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest9' doesn't exist
sysbench *.* * (glob)
Running the test with following options:
Number of threads: 2
Initializing random number generator from current time
Initializing worker threads...
Threads started!
OLTP test statistics:
queries performed:
read: 1400
write: 400
other: 200
total: 2000
transactions: 100 (* per sec.) (glob)
queries: 2000 (* per sec.) (glob)
ignored errors: 0 (* per sec.) (glob)
reconnects: 0 (* per sec.) (glob)
General statistics:
total time: *s (glob)
total number of events: 100
total time taken by event execution: *s (glob)
Latency statistics:
min: *.*ms (glob)
avg: *.*ms (glob)
max: *.*ms (glob)
approx. 95th percentile: *.*ms (glob)
Threads fairness:
events (avg/stddev): */* (glob)
execution time (avg/stddev): */* (glob)
sysbench *.* * (glob)
Dropping table 'sbtest1'...
Dropping table 'sbtest2'...
Dropping table 'sbtest3'...
Dropping table 'sbtest4'...
Dropping table 'sbtest5'...
Dropping table 'sbtest6'...
Dropping table 'sbtest7'...
Dropping table 'sbtest8'...
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest1' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest2' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest3' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest4' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest5' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest6' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest7' doesn't exist
ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest8' doesn't exist
sysbench * (glob)
Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
*************************** 1. row ***************************
sbtest1
CREATE TABLE `sbtest1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`k` int(10) unsigned NOT NULL DEFAULT '0',
`c` char(120)* NOT NULL DEFAULT '', (glob)
`pad` char(60)* NOT NULL DEFAULT '', (glob)
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob)
sysbench * (glob)
Dropping table 'sbtest1'...

View File

@ -9,40 +9,61 @@ SQL Lua API tests
$ SB_ARGS="--verbosity=1 --test=$CRAMTMP/api_sql.lua --max-requests=1 --num-threads=1 --db-driver=mysql $SBTEST_MYSQL_ARGS"
$ cat >$CRAMTMP/api_sql.lua <<EOF
> function event(thread_id)
> db_query("CREATE TABLE t(a INT)")
> function thread_init()
> drv = sysbench.sql.driver()
> con = drv:connect()
> end
>
> db_bulk_insert_init("INSERT INTO t VALUES")
> function event()
> for k,v in pairs(sysbench.sql.type) do print(k .. " = " .. v) end
> print()
>
> con:query("DROP TABLE IF EXISTS t")
> con:query("CREATE TABLE t(a INT)")
> con:bulk_insert_init("INSERT INTO t VALUES")
> for i = 1,100 do
> db_bulk_insert_next(string.format("(%d)", i))
> con:bulk_insert_next(string.format("(%d)", i))
> end
> db_bulk_insert_done()
> con:bulk_insert_done()
>
> db_connect()
> db_query("SELECT 1")
> db_disconnect()
> db_query("SELECT 1")
> db_connect()
> con2 = drv:connect()
> con:query("SELECT CONNECTION_ID()")
> con2:query("SELECT CONNECTION_ID()")
> con2:disconnect()
>
> local stmt = db_prepare("UPDATE t SET a = a + ?")
> db_bind_param(stmt, {100})
> rs = db_execute(stmt)
> db_store_results(rs)
> db_free_results(rs)
> db_close(stmt)
>
> print("DB_ERROR_NONE = " .. DB_ERROR_NONE)
> print("DB_ERROR_RESTART_TRANSACTION = " .. DB_ERROR_RESTART_TRANSACTION)
> print("DB_ERROR_FAILED = " .. DB_ERROR_FAILED)
> con:query("SELECT 1")
> con:disconnect()
> con:query("SELECT 1")
>
> con = drv:connect()
> con:query[[UPDATE t SET a = a + 100]]
>
> -- local stmt = con:prepare("UPDATE t SET a = a + ?")
> -- stmt:bind_param({{sysbench.sql.type.INT}})
> -- rs = stmt:execute()
> -- rs:free_results()
> -- stmt:close()
> end
> EOF
$ mysql -uroot sbtest -Nse "DROP TABLE IF EXISTS t"
$ sysbench $SB_ARGS run
DB_ERROR_NONE = 0
DB_ERROR_RESTART_TRANSACTION = 1
DB_ERROR_FAILED = 3
NONE = 0
INT = 3
CHAR = 11
VARCHAR = 12
TIMESTAMP = 10
TIME = 7
FLOAT = 5
TINYINT = 1
BIGINT = 4
SMALLINT = 2
DATE = 8
DATETIME = 9
DOUBLE = 6
ALERT: attempt to use an already closed connection
$ mysql -uroot sbtest -Nse "SHOW CREATE TABLE t\G"
*************************** 1. row ***************************

View File

@ -25,9 +25,8 @@ MySQL driver tests
write: 0
other: 0
total: 10
transactions: 0 (0.00 per sec.)
read/write requests: 10 (*.* per sec.) (glob)
other operations: 0 (0.00 per sec.)
transactions: 10 (*.* per sec.) (glob)
queries: 10 (*.* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)

View File

@ -25,9 +25,8 @@ PostgreSQL driver tests
write: 0
other: 0
total: 10
transactions: 0 (0.00 per sec.)
read/write requests: 10 (*.* per sec.) (glob)
other operations: 0 (0.00 per sec.)
transactions: 10 (*.* per sec.) (glob)
queries: 10 (*.* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)

View File

@ -8,7 +8,7 @@
> fi
$ sysbench --test=${SBTEST_SCRIPTDIR}/oltp.lua --db-driver=mysql --mysql-dry-run --max-time=3 --max-requests=0 --report-interval=1 run | grep '\[ 2s\]'
[ 2s] threads: 1, tps: *, reads: *, writes: *, response time: *ms (95%), errors: 0.00, reconnects: 0.00 (glob)
[ 2s] threads: 1 tps: * qps: * (r/w/o: */*/*) latency: *ms (95%) errors/s: 0.00 reconnects/s: 0.00 (glob)
# Run a test that does not support intermediate reports

View File

@ -138,8 +138,7 @@ oltp.lua + MySQL tests
other: 200
total: 2000
transactions: 100 (* per sec.) (glob)
read/write requests: 1800 (* per sec.) (glob)
other operations: 200 (* per sec.) (glob)
queries: 2000 (* per sec.) (glob)
ignored errors: 0 (* per sec.) (glob)
reconnects: 0 (* per sec.) (glob)
@ -320,8 +319,7 @@ oltp.lua + MySQL tests
other: 200
total: 2000
transactions: 100 (* per sec.) (glob)
read/write requests: 1800 (* per sec.) (glob)
other operations: 200 (* per sec.) (glob)
queries: 2000 (* per sec.) (glob)
ignored errors: 0 (* per sec.) (glob)
reconnects: 0 (* per sec.) (glob)

View File

@ -147,8 +147,7 @@ oltp.lua + PostgreSQL tests
other: 200
total: 2000
transactions: 100 (* per sec.) (glob)
read/write requests: 1800 (* per sec.) (glob)
other operations: 200 (* per sec.) (glob)
queries: 2000 (* per sec.) (glob)
ignored errors: 0 (* per sec.) (glob)
reconnects: 0 (* per sec.) (glob)

View File

@ -53,8 +53,7 @@ select_random_*.lua + MySQL tests
other: 0
total: 100
transactions: 0 (0.00 per sec.)
read/write requests: 100 (* per sec.) (glob)
other operations: 0 (0.00 per sec.)
queries: 100 (* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
@ -124,8 +123,7 @@ select_random_*.lua + MySQL tests
other: 0
total: 100
transactions: 0 (0.00 per sec.)
read/write requests: 100 (* per sec.) (glob)
other operations: 0 (0.00 per sec.)
queries: 100 (* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)

View File

@ -54,8 +54,7 @@ select_random_*.lua + PostgreSQL tests
other: 0
total: 100
transactions: 0 (0.00 per sec.)
read/write requests: 100 (* per sec.) (glob)
other operations: 0 (0.00 per sec.)
queries: 100 (* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
@ -126,8 +125,7 @@ select_random_*.lua + PostgreSQL tests
other: 0
total: 100
transactions: 0 (0.00 per sec.)
read/write requests: 100 (* per sec.) (glob)
other operations: 0 (0.00 per sec.)
queries: 100 (* per sec.) (glob)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)

View File

@ -65,7 +65,7 @@ else
fi
export SBTEST_ROOTDIR="$testroot"
export SBTEST_SCRIPTDIR="$testroot/../sysbench/tests/db"
export SBTEST_SCRIPTDIR="$testroot/../sysbench/lua"
export SBTEST_SUITEDIR="$testroot/t"
export SBTEST_INCDIR="$PWD/include"
export SBTEST_CONFIG="$SBTEST_INCDIR/config.sh"