Fixes #13: Export db_fetch_row
Add support for result set retrieving for MySQL and PostgreSQL drivers and export it to the new Lua SQL API.
This commit is contained in:
@ -537,22 +537,28 @@ db_row_t *db_fetch_row(db_result_t *rs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (rs->row != NULL)
|
||||
db_free_row(rs->row);
|
||||
rs->row = (db_row_t *)calloc(1, sizeof(db_row_t));
|
||||
if (rs->row == NULL)
|
||||
return NULL;
|
||||
|
||||
if (con->driver->ops.fetch_row(rs, rs->row))
|
||||
if (con->driver->ops.fetch_row == NULL)
|
||||
{
|
||||
db_free_row(rs->row);
|
||||
log_text(LOG_ALERT, "fetching rows is not supported by the driver");
|
||||
}
|
||||
|
||||
if (rs->nrows == 0 || rs->nfields == 0)
|
||||
{
|
||||
log_text(LOG_ALERT, "attempt to fetch row from an empty result set");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rs->row;
|
||||
#endif
|
||||
return NULL;
|
||||
if (rs->row.values == NULL)
|
||||
{
|
||||
rs->row.values = malloc(rs->nfields * sizeof(db_value_t));
|
||||
}
|
||||
|
||||
if (con->driver->ops.fetch_row(rs, &rs->row))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &rs->row;
|
||||
}
|
||||
|
||||
|
||||
@ -594,10 +600,16 @@ static int db_free_results_int(db_conn_t *con)
|
||||
|
||||
rc = con->driver->ops.free_results(&con->rs);
|
||||
|
||||
#if 0
|
||||
if (rs->row != NULL)
|
||||
db_free_row(rs->row);
|
||||
#endif
|
||||
if (con->rs.row.values != NULL)
|
||||
{
|
||||
free(con->rs.row.values);
|
||||
con->rs.row.values = NULL;
|
||||
}
|
||||
|
||||
con->rs.nrows = 0;
|
||||
con->rs.nfields = 0;
|
||||
|
||||
con->rs.statement = NULL;
|
||||
|
||||
con->state = DB_CONN_READY;
|
||||
|
||||
@ -628,9 +640,18 @@ int db_free_results(db_result_t *rs)
|
||||
int db_close(db_stmt_t *stmt)
|
||||
{
|
||||
int rc;
|
||||
db_conn_t *con;
|
||||
db_conn_t *con = stmt->connection;
|
||||
|
||||
con = stmt->connection;
|
||||
if (con->state == DB_CONN_INVALID)
|
||||
{
|
||||
log_text(LOG_ALERT, "attempt to use an already closed connection");
|
||||
return 0;
|
||||
}
|
||||
else if (con->state == DB_CONN_RESULT_SET &&
|
||||
(rc = db_free_results_int(con)) != 0)
|
||||
{
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (con->state == DB_CONN_INVALID)
|
||||
{
|
||||
@ -836,7 +857,6 @@ int db_bulk_insert_init(db_conn_t *con, const char *query, size_t query_len)
|
||||
if (con->bulk_buffer == NULL)
|
||||
return 1;
|
||||
|
||||
con->bulk_supported = driver_caps.multi_rows_insert;
|
||||
con->bulk_commit_max = driver_caps.needs_commit ? ROWS_BEFORE_COMMIT : 0;
|
||||
con->bulk_commit_cnt = 0;
|
||||
strcpy(con->bulk_buffer, query);
|
||||
|
||||
@ -186,14 +186,31 @@ typedef enum {
|
||||
DB_STAT_MAX
|
||||
} db_stat_type_t;
|
||||
|
||||
/* Row value definition */
|
||||
|
||||
typedef struct {
|
||||
uint32_t len; /* Value length */
|
||||
const char *ptr; /* Value string */
|
||||
} db_value_t;
|
||||
|
||||
/* Result set row definition */
|
||||
|
||||
typedef struct db_row
|
||||
{
|
||||
void *ptr; /* Driver-specific row data */
|
||||
db_value_t *values; /* Array of column values */
|
||||
} db_row_t;
|
||||
|
||||
/* Result set definition */
|
||||
|
||||
typedef struct db_result
|
||||
{
|
||||
db_stat_type_t stat_type; /* Statistical counter type */
|
||||
uint32_t nrows; /* Number of affected rows */
|
||||
uint32_t nfields; /* Number of fields */
|
||||
struct db_stmt *statement; /* Pointer to prepared statement (if used) */
|
||||
void *ptr; /* Pointer to driver-specific data */
|
||||
db_row_t row; /* Last fetched row */
|
||||
} db_result_t;
|
||||
|
||||
typedef enum {
|
||||
@ -211,11 +228,8 @@ typedef struct db_conn
|
||||
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 */
|
||||
int thread_id; /* Thread this connection belongs to */
|
||||
|
||||
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 */
|
||||
unsigned int bulk_buflen; /* Current length of bulk_buffer */
|
||||
char *bulk_buffer; /* Bulk insert query buffer */
|
||||
@ -245,14 +259,6 @@ typedef struct db_stmt
|
||||
void *ptr; /* Pointer to driver-specific data structure */
|
||||
} db_stmt_t;
|
||||
|
||||
/* Result set row definition */
|
||||
|
||||
typedef struct db_row
|
||||
{
|
||||
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.
|
||||
|
||||
@ -167,9 +167,7 @@ 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 *);
|
||||
@ -195,11 +193,7 @@ static db_driver_t mysql_driver =
|
||||
.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,
|
||||
@ -916,7 +910,10 @@ db_error_t mysql_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
|
||||
rs->ptr = (void *)res;
|
||||
|
||||
rs->nrows = mysql_num_rows(res);
|
||||
DEBUG("mysql_num_rows(%p) = %u", res, (unsigned int)rs->nrows);
|
||||
DEBUG("mysql_num_rows(%p) = %u", res, (unsigned int) rs->nrows);
|
||||
|
||||
rs->nfields = mysql_num_fields(res);
|
||||
DEBUG("mysql_num_fields(%p) = %u", res, (unsigned int) rs->nfields);
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
@ -936,29 +933,30 @@ int mysql_drv_fetch(db_result_t *rs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Fetch row from result set of a query */
|
||||
|
||||
|
||||
int mysql_drv_fetch_row(db_result_t *rs, db_row_t *row)
|
||||
{
|
||||
MYSQL_ROW my_row;
|
||||
|
||||
if (args.dry_run)
|
||||
return DB_ERROR_NONE;
|
||||
|
||||
db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) rs->connection->ptr;
|
||||
row->ptr = mysql_fetch_row(rs->ptr);
|
||||
DEBUG("mysql_fetch_row(%p) = %p", rs->ptr, row->ptr);
|
||||
if (row->ptr == NULL)
|
||||
my_row = mysql_fetch_row(rs->ptr);
|
||||
DEBUG("mysql_fetch_row(%p) = %p", rs->ptr, my_row);
|
||||
|
||||
unsigned long *lengths = mysql_fetch_lengths(rs->ptr);
|
||||
if (lengths == NULL)
|
||||
return DB_ERROR_NONE;
|
||||
|
||||
for (size_t i = 0; i < rs->nfields; i++)
|
||||
{
|
||||
log_text(LOG_FATAL, "mysql_fetch_row() failed: %s",
|
||||
mysql_error(db_mysql_con->mysql));
|
||||
return 1;
|
||||
row->values[i].len = lengths[i];
|
||||
row->values[i].ptr = my_row[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free result set */
|
||||
|
||||
|
||||
@ -477,7 +477,9 @@ static db_error_t pgsql_check_status(PGconn *pgcon, PGresult *pgres,
|
||||
switch(status) {
|
||||
case PGRES_TUPLES_OK:
|
||||
rs->nrows = PQntuples(pgres);
|
||||
rs->nfields = PQnfields(pgres);
|
||||
rs->stat_type = DB_STAT_READ;
|
||||
|
||||
rc = DB_ERROR_NONE;
|
||||
|
||||
break;
|
||||
@ -656,11 +658,35 @@ int pgsql_drv_fetch(db_result_t *rs)
|
||||
|
||||
int pgsql_drv_fetch_row(db_result_t *rs, db_row_t *row)
|
||||
{
|
||||
/* NYI */
|
||||
(void)rs; /* unused */
|
||||
(void)row; /* unused */
|
||||
|
||||
return 1;
|
||||
intptr_t rownum;
|
||||
int i;
|
||||
|
||||
/*
|
||||
Use row->ptr as a row number, rather than a pointer to avoid dynamic
|
||||
memory management.
|
||||
*/
|
||||
rownum = (intptr_t) row->ptr;
|
||||
if (rownum >= (int) rs->nrows)
|
||||
return DB_ERROR_NONE;
|
||||
|
||||
for (i = 0; i < (int) rs->nfields; i++)
|
||||
{
|
||||
/*
|
||||
PQgetvalue() returns an empty string, not a NULL value for a NULL
|
||||
field. Callers of this function expect a NULL pointer in this case.
|
||||
*/
|
||||
if (PQgetisnull(rs->ptr, rownum, i))
|
||||
row->values[i].ptr = NULL;
|
||||
else
|
||||
{
|
||||
row->values[i].len = PQgetlength(rs->ptr, rownum, i);
|
||||
row->values[i].ptr = PQgetvalue(rs->ptr, rownum, i);
|
||||
}
|
||||
}
|
||||
|
||||
row->ptr = (void *) (rownum + 1);
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -673,6 +699,8 @@ int pgsql_drv_free_results(db_result_t *rs)
|
||||
{
|
||||
PQclear((PGresult *)rs->ptr);
|
||||
rs->ptr = NULL;
|
||||
|
||||
rs->row.ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,10 @@ ffi = require("ffi")
|
||||
sysbench.sql = {}
|
||||
|
||||
ffi.cdef[[
|
||||
/*
|
||||
The following definitions have been copied with modifications from db_driver.h
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_ERROR_NONE, /* no error(s) */
|
||||
@ -39,9 +43,46 @@ typedef struct
|
||||
const char opaque[?];
|
||||
} sql_driver;
|
||||
|
||||
typedef struct {
|
||||
uint32_t len; /* Value length */
|
||||
const char *ptr; /* Value string */
|
||||
} sql_value;
|
||||
|
||||
/* Result set row definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *ptr; /* Driver-specific row data */
|
||||
sql_value *values; /* Array of column values */
|
||||
} sql_row;
|
||||
|
||||
/* Query type for statistics */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_STAT_OTHER,
|
||||
DB_STAT_READ,
|
||||
DB_STAT_WRITE,
|
||||
DB_STAT_TRX,
|
||||
DB_STAT_ERROR,
|
||||
DB_STAT_RECONNECT,
|
||||
DB_STAT_MAX
|
||||
} sql_stat_type;
|
||||
|
||||
typedef struct db_conn sql_connection;
|
||||
typedef struct db_stmt sql_statement;
|
||||
typedef struct db_result sql_result;
|
||||
|
||||
/* Result set definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sql_stat_type stat_type; /* Statistical counter type */
|
||||
uint32_t nrows; /* Number of affected rows */
|
||||
uint32_t nfields; /* Number of fields */
|
||||
sql_statement *statement; /* Pointer to prepared statement (if used) */
|
||||
void *ptr; /* Pointer to driver-specific data */
|
||||
sql_row row; /* Last fetched row */
|
||||
} sql_result;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -82,6 +123,8 @@ void db_bulk_insert_done(sql_connection *);
|
||||
|
||||
sql_result *db_query(sql_connection *con, const char *query, size_t len);
|
||||
|
||||
sql_row *db_fetch_row(sql_result *rs);
|
||||
|
||||
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);
|
||||
@ -96,6 +139,8 @@ local sql_connection = ffi.typeof('sql_connection *')
|
||||
local sql_statement = ffi.typeof('sql_statement *')
|
||||
local sql_bind = ffi.typeof('sql_bind');
|
||||
local sql_result = ffi.typeof('sql_result');
|
||||
local sql_value = ffi.typeof('sql_value');
|
||||
local sql_row = ffi.typeof('sql_row');
|
||||
|
||||
sysbench.sql.type =
|
||||
{
|
||||
@ -268,6 +313,41 @@ function sysbench.sql.close(stmt)
|
||||
return ffi.C.db_close(stmt)
|
||||
end
|
||||
|
||||
-- Returns the next row of values from a result set, or nil if there are no more
|
||||
-- rows to fetch. Values are returned as an array, i.e. a table with numeric
|
||||
-- indexes starting from 1. The total number of values (i.e. fields in a result
|
||||
-- set) can be obtained from sql_result.nfields.
|
||||
function sysbench.sql.fetch_row(rs)
|
||||
check_type(sql_result, rs, 'sysbench.sql.fetch_row')
|
||||
|
||||
local res = {}
|
||||
local row = ffi.C.db_fetch_row(rs)
|
||||
|
||||
if row == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local i
|
||||
for i = 0, rs.nfields-1 do
|
||||
if row.values[i].ptr ~= nil then -- not a NULL value
|
||||
res[i+1] = ffi.string(row.values[i].ptr, tonumber(row.values[i].len))
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
function sysbench.sql.query_row(con, query)
|
||||
check_type(sql_connection, con, 'sysbench.sql.query_row')
|
||||
|
||||
local rs = con:query(query)
|
||||
if rs == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
return unpack(rs:fetch_row(), 1, rs.nfields)
|
||||
end
|
||||
|
||||
function sysbench.sql.free_results(result)
|
||||
check_type(sql_result, result, 'sysbench.sql.free_results')
|
||||
return ffi.C.db_free_results(result)
|
||||
@ -293,6 +373,7 @@ local connection_mt = {
|
||||
__index = {
|
||||
disconnect = sysbench.sql.disconnect,
|
||||
query = sysbench.sql.query,
|
||||
query_row = sysbench.sql.query_row,
|
||||
bulk_insert_init = sysbench.sql.bulk_insert_init,
|
||||
bulk_insert_next = sysbench.sql.bulk_insert_next,
|
||||
bulk_insert_done = sysbench.sql.bulk_insert_done,
|
||||
@ -329,7 +410,8 @@ ffi.metatype("sql_bind", bind_mt)
|
||||
-- sql_results metatable
|
||||
local result_mt = {
|
||||
__index = {
|
||||
free = sysbench.sql.free_results
|
||||
fetch_row = sysbench.sql.fetch_row,
|
||||
free = sysbench.sql.free_results,
|
||||
},
|
||||
__tostring = function() return '<sql_result>' end,
|
||||
__gc = sysbench.sql.free_results
|
||||
|
||||
103
tests/include/api_sql_common.sh
Normal file
103
tests/include/api_sql_common.sh
Normal file
@ -0,0 +1,103 @@
|
||||
########################################################################
|
||||
# Common code for SQL API 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
|
||||
#
|
||||
########################################################################
|
||||
|
||||
set -eu
|
||||
|
||||
SB_ARGS="--verbosity=1 --test=$CRAMTMP/api_sql.lua --max-requests=1 --num-threads=1 $DB_DRIVER_ARGS"
|
||||
cat >$CRAMTMP/api_sql.lua <<EOF
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = drv:connect()
|
||||
end
|
||||
|
||||
function event()
|
||||
print("drv:name() = " .. drv:name())
|
||||
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
|
||||
con:bulk_insert_next(string.format("(%d)", i))
|
||||
end
|
||||
con:bulk_insert_done()
|
||||
print(con:query_row("SELECT COUNT(DISTINCT a) FROM t"))
|
||||
print('--')
|
||||
con:query("DROP TABLE IF EXISTS t2")
|
||||
con:query("CREATE TABLE t2(a INT, b VARCHAR(120), c FLOAT)")
|
||||
con:query("INSERT INTO t2 VALUES (1, 'foo', 0.4)")
|
||||
con:query("INSERT INTO t2 VALUES (NULL, 'bar', 0.2)")
|
||||
con:query("INSERT INTO t2 VALUES (2, NULL, 0.3)")
|
||||
con:query("INSERT INTO t2 VALUES (NULL, NULL, 0.1)")
|
||||
|
||||
print('--')
|
||||
local rs = con:query("SELECT * FROM t2 ORDER BY a")
|
||||
for i = 1, rs.nrows do
|
||||
print(string.format("%s %s %s", unpack(rs:fetch_row(), 1, rs.nfields)))
|
||||
end
|
||||
print('--')
|
||||
|
||||
print(string.format("%s %s", con:query_row("SELECT b, a FROM t2 ORDER BY b")))
|
||||
print('--')
|
||||
con:query("DROP TABLE t2")
|
||||
con:query("ALTER TABLE t ADD COLUMN b CHAR(10)")
|
||||
|
||||
local stmt = con:prepare("UPDATE t SET a = a + ?, b = ?")
|
||||
local a = stmt:bind_create(sysbench.sql.type.INT)
|
||||
local b = stmt:bind_create(sysbench.sql.type.CHAR, 10)
|
||||
stmt:bind_param(a, b)
|
||||
a:set(100)
|
||||
rs = stmt:execute()
|
||||
a:set(200)
|
||||
b:set("01234567890")
|
||||
rs = stmt:execute()
|
||||
rs:free()
|
||||
stmt:close()
|
||||
|
||||
rs = con:query("SELECT MIN(a), MAX(a), MIN(b), MAX(b) FROM t")
|
||||
print(rs.nfields)
|
||||
for i = 1, rs.nrows do
|
||||
print(string.format("%s %s %s %s", unpack(rs:fetch_row(), 1, rs.nfields)))
|
||||
end
|
||||
con:query("DROP TABLE t")
|
||||
print('--')
|
||||
end
|
||||
EOF
|
||||
|
||||
sysbench $SB_ARGS run
|
||||
|
||||
########################################################################
|
||||
# Multiple connections test
|
||||
########################################################################
|
||||
cat >$CRAMTMP/api_sql.lua <<EOF
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = {}
|
||||
for i=1,10 do
|
||||
con[i] = drv:connect()
|
||||
end
|
||||
end
|
||||
|
||||
function event()
|
||||
con[1]:query("DROP TABLE IF EXISTS t")
|
||||
con[2]:query("CREATE TABLE t(a INT)")
|
||||
for i=1,10 do
|
||||
con[i]:query("INSERT INTO t VALUES (" .. i .. ")")
|
||||
end
|
||||
rs = con[1]:query("SELECT * FROM t")
|
||||
for i = 1, rs.nrows do
|
||||
print(string.format("%s", unpack(rs:fetch_row(), 1, rs.nfields)))
|
||||
end
|
||||
con[1]:query("DROP TABLE t")
|
||||
end
|
||||
EOF
|
||||
|
||||
sysbench $SB_ARGS run
|
||||
15
tests/include/mysql_common.sh
Normal file
15
tests/include/mysql_common.sh
Normal file
@ -0,0 +1,15 @@
|
||||
########################################################################
|
||||
# Common code for MySQL-specific tests
|
||||
########################################################################
|
||||
set -eu
|
||||
|
||||
if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
then
|
||||
exit 80
|
||||
fi
|
||||
|
||||
function db_show_table() {
|
||||
mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
}
|
||||
|
||||
DB_DRIVER_ARGS="--db-driver=mysql $SBTEST_MYSQL_ARGS"
|
||||
15
tests/include/pgsql_common.sh
Normal file
15
tests/include/pgsql_common.sh
Normal file
@ -0,0 +1,15 @@
|
||||
########################################################################
|
||||
# Common code for PostgreSQL-specific tests
|
||||
########################################################################
|
||||
set -eu
|
||||
|
||||
if [ -z "${SBTEST_PGSQL_ARGS:-}" ]
|
||||
then
|
||||
exit 80
|
||||
fi
|
||||
|
||||
function db_show_table() {
|
||||
psql -c "\d+ $1" sbtest
|
||||
}
|
||||
|
||||
DB_DRIVER_ARGS="--db-driver=pgsql $SBTEST_PGSQL_ARGS"
|
||||
@ -2,11 +2,6 @@
|
||||
Basic Lua API tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ SB_ARGS="--verbosity=0 --test=$CRAMTMP/api_basic.lua --max-requests=2 --num-threads=1 --db-driver=mysql $SBTEST_MYSQL_ARGS"
|
||||
|
||||
$ cat >$CRAMTMP/api_basic.lua <<EOF
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
########################################################################
|
||||
SQL Lua API tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ 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 thread_init()
|
||||
> drv = sysbench.sql.driver()
|
||||
> con = drv:connect()
|
||||
> end
|
||||
>
|
||||
> function event()
|
||||
> print("drv:name() = " .. drv:name())
|
||||
> 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
|
||||
> con:bulk_insert_next(string.format("(%d)", i))
|
||||
> end
|
||||
> con:bulk_insert_done()
|
||||
>
|
||||
> con2 = drv:connect()
|
||||
> con:query("SELECT CONNECTION_ID()")
|
||||
> con2:query("SELECT CONNECTION_ID()")
|
||||
> con2:disconnect()
|
||||
>
|
||||
> con:query("SELECT 1")
|
||||
> con:disconnect()
|
||||
> con:query("SELECT 1")
|
||||
>
|
||||
> con = drv:connect()
|
||||
>
|
||||
> con:query("ALTER TABLE t ADD COLUMN b CHAR(10)")
|
||||
>
|
||||
> local stmt = con:prepare("UPDATE t SET a = a + ?, b = ?")
|
||||
> local a = stmt:bind_create(sysbench.sql.type.INT)
|
||||
> local b = stmt:bind_create(sysbench.sql.type.CHAR, 10)
|
||||
> stmt:bind_param(a, b)
|
||||
> a:set(100)
|
||||
> rs = stmt:execute()
|
||||
> a:set(200)
|
||||
> b:set("01234567890")
|
||||
> rs = stmt:execute()
|
||||
> rs:free()
|
||||
> stmt:close()
|
||||
> end
|
||||
> EOF
|
||||
|
||||
$ mysql -uroot sbtest -Nse "DROP TABLE IF EXISTS t"
|
||||
|
||||
$ sysbench $SB_ARGS run
|
||||
drv:name() = mysql
|
||||
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 ***************************
|
||||
t
|
||||
CREATE TABLE `t` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`b` char(10)* DEFAULT NULL (glob)
|
||||
) * (glob)
|
||||
|
||||
$ mysql -uroot sbtest -Nse "SELECT COUNT(DISTINCT a) FROM t"
|
||||
100
|
||||
|
||||
$ mysql -uroot sbtest -Nse "SELECT MIN(a), MAX(a), MIN(b), MAX(b) FROM t\G"
|
||||
*************************** 1. row ***************************
|
||||
301
|
||||
400
|
||||
0123456789
|
||||
0123456789
|
||||
|
||||
$ mysql -uroot sbtest -Nse "DROP TABLE t"
|
||||
|
||||
########################################################################
|
||||
Multiple connections test
|
||||
########################################################################
|
||||
$ 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 thread_init()
|
||||
> drv = sysbench.sql.driver()
|
||||
> con = {}
|
||||
> for i=1,10 do
|
||||
> con[i] = drv:connect()
|
||||
> end
|
||||
> end
|
||||
>
|
||||
> function event()
|
||||
> con[1]:query("DROP TABLE IF EXISTS t")
|
||||
> con[2]:query("CREATE TABLE t(a INT)")
|
||||
> for i=1,10 do
|
||||
> con[i]:query("INSERT INTO t VALUES (" .. i .. ")")
|
||||
> end
|
||||
> end
|
||||
> EOF
|
||||
|
||||
$ sysbench $SB_ARGS run
|
||||
$ mysql -uroot sbtest -Nse "SELECT * FROM t"
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
$ mysql -uroot sbtest -Nse "DROP TABLE t"
|
||||
44
tests/t/api_sql_mysql.t
Normal file
44
tests/t/api_sql_mysql.t
Normal file
@ -0,0 +1,44 @@
|
||||
########################################################################
|
||||
SQL Lua API + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ . ${SBTEST_INCDIR}/mysql_common.sh
|
||||
$ . ${SBTEST_INCDIR}/api_sql_common.sh
|
||||
drv:name() = mysql
|
||||
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
|
||||
|
||||
100
|
||||
--
|
||||
--
|
||||
nil bar 0.2
|
||||
nil nil 0.1
|
||||
1 foo 0.4
|
||||
2 nil 0.3
|
||||
--
|
||||
nil 2
|
||||
--
|
||||
4
|
||||
301 400 0123456789 0123456789
|
||||
--
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
47
tests/t/api_sql_pgsql.t
Normal file
47
tests/t/api_sql_pgsql.t
Normal file
@ -0,0 +1,47 @@
|
||||
########################################################################
|
||||
SQL Lua API + PostgreSQL tests
|
||||
########################################################################
|
||||
|
||||
$ . ${SBTEST_INCDIR}/pgsql_common.sh
|
||||
$ . ${SBTEST_INCDIR}/api_sql_common.sh
|
||||
drv:name() = pgsql
|
||||
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
|
||||
|
||||
NOTICE: table "t" does not exist, skipping
|
||||
100
|
||||
--
|
||||
NOTICE: table "t2" does not exist, skipping
|
||||
--
|
||||
1 foo 0.4
|
||||
2 nil 0.3
|
||||
nil bar 0.2
|
||||
nil nil 0.1
|
||||
--
|
||||
bar nil
|
||||
--
|
||||
4
|
||||
301 400 0123456789 0123456789
|
||||
--
|
||||
NOTICE: table "t" does not exist, skipping
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
@ -2,11 +2,7 @@
|
||||
MySQL driver tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql $SBTEST_MYSQL_ARGS"
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ . $SBTEST_INCDIR/drv_common.sh
|
||||
sysbench *.* * (glob)
|
||||
|
||||
|
||||
@ -2,16 +2,7 @@
|
||||
bulk_insert.lua + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ function db_show_table() {
|
||||
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
> }
|
||||
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql $SBTEST_MYSQL_ARGS"
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ . $SBTEST_INCDIR/script_bulk_insert_common.sh
|
||||
Creating table 'sbtest1'...
|
||||
Creating table 'sbtest2'...
|
||||
|
||||
@ -2,16 +2,7 @@
|
||||
oltp_point_select.lua + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ function db_show_table() {
|
||||
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
> }
|
||||
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=innodb $SBTEST_MYSQL_ARGS"
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ OLTP_SCRIPT_PATH=${SBTEST_SCRIPTDIR}/oltp_insert.lua
|
||||
$ . $SBTEST_INCDIR/script_oltp_common.sh
|
||||
sysbench *.* * (glob)
|
||||
|
||||
@ -2,16 +2,7 @@
|
||||
oltp_point_select.lua + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ function db_show_table() {
|
||||
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
> }
|
||||
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=innodb $SBTEST_MYSQL_ARGS"
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ OLTP_SCRIPT_PATH=${SBTEST_SCRIPTDIR}/oltp_point_select.lua
|
||||
$ . $SBTEST_INCDIR/script_oltp_common.sh
|
||||
sysbench *.* * (glob)
|
||||
|
||||
@ -2,15 +2,7 @@
|
||||
oltp_read_write.lua + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ function db_show_table() {
|
||||
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
> }
|
||||
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=myisam $SBTEST_MYSQL_ARGS"
|
||||
$ OLTP_SCRIPT_PATH=${SBTEST_SCRIPTDIR}/oltp_read_write.lua
|
||||
$ . $SBTEST_INCDIR/script_oltp_common.sh
|
||||
|
||||
@ -2,16 +2,7 @@
|
||||
select_random_*.lua + MySQL tests
|
||||
########################################################################
|
||||
|
||||
$ if [ -z "${SBTEST_MYSQL_ARGS:-}" ]
|
||||
> then
|
||||
> exit 80
|
||||
> fi
|
||||
|
||||
$ function db_show_table() {
|
||||
> mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G"
|
||||
> }
|
||||
|
||||
$ DB_DRIVER_ARGS="--db-driver=mysql $SBTEST_MYSQL_ARGS"
|
||||
$ . $SBTEST_INCDIR/mysql_common.sh
|
||||
$ . $SBTEST_INCDIR/script_select_random_common.sh
|
||||
sysbench * (glob)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user