Commit 8d7f8108 authored by Michael Widenius's avatar Michael Widenius

Upgraded to latest handlersocket code. This fixed LP:766870 "Assertion...

Upgraded to latest handlersocket code. This fixed LP:766870  "Assertion `next_insert_id == 0' failed with handlersocket"

sql/handler.cc:
  Added DBUG_ code
parent 2740edcf
......@@ -84,7 +84,6 @@ TEST_DIRS = t r include std_data std_data/parts collections \
std_data/funcs_1 \
extra/binlog_tests/ extra/rpl_tests \
suite/binlog suite/binlog/t suite/binlog/r suite/binlog/std_data \
suite/bugs suite/bugs/data suite/bugs/t suite/bugs/r \
suite/federated \
suite/pbxt/t suite/pbxt/r suite/pbxt \
suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \
......
......@@ -17,3 +17,6 @@ Moriyoshi Koizumi (https://github.com/moriyoshi)
takeda-at (https://github.com/takada-at)
- added simple authorization function
WheresWardy (https://github.com/WheresWardy)
- added authentication functions to libhsclient
......@@ -6,9 +6,19 @@ hsclient_LDFLAGS= -static -L../libhsclient -lhsclient
hsclient_CXXFLAGS= $(AM_INCLUDES)
hstest: hstest.o
$(CXX) $(CXXFLAGS) $(LFLAGS) hstest.o \
-L../libhsclient/.libs -lhsclient $(MYSQL_LIB) -o hstest
$(CXX) $(CXXFLAGS) $(MY_CXXFLAGS) $(LFLAGS) hstest.o \
-L../libhsclient/.libs -lhsclient $(MYSQL_LIB) \
-o hstest
hstest.o: hstest.cpp
$(CXX) $(CXXFLAGS) $(MYSQL_INC) $(AM_INCLUDES) -c hstest.cpp
$(CXX) $(CXXFLAGS) $(MY_CXXFLAGS) $(MYSQL_INC) $(AM_INCLUDES) \
-c hstest.cpp
hslongrun: hslongrun.o
$(CXX) $(CXXFLAGS) $(MY_CXXFLAGS) $(LFLAGS) hslongrun.o \
-L../libhsclient/.libs -lhsclient $(MYSQL_LIB) \
-o hslongrun
hslongrun.o: hslongrun.cpp
$(CXX) $(CXXFLAGS) $(MY_CXXFLAGS) $(MYSQL_INC) $(AM_INCLUDES) \
-c hslongrun.cpp
This diff is collapsed.
......@@ -92,7 +92,7 @@ namespace {
double
gettimeofday_double()
{
struct timeval tv = { };
struct timeval tv;
if (gettimeofday(&tv, 0) != 0) {
fatal_abort("gettimeofday");
}
......@@ -552,7 +552,8 @@ hstest_thread::test_9(int test_num)
"moreflds_prefix", "column0123456789_");
const int use_handler = arg.sh.conf.get_int("handler", 0);
const int sched_flag = arg.sh.conf.get_int("sched", 0);
const int ssps = arg.sh.conf.get_int("ssps", 0);
const int use_in = arg.sh.conf.get_int("in", 0);
const int ssps = use_in ? 0 : arg.sh.conf.get_int("ssps", 0);
std::string flds = "v";
for (int i = 0; i < moreflds; ++i) {
char buf[1024];
......@@ -561,6 +562,7 @@ hstest_thread::test_9(int test_num)
}
int connected = 0;
std::auto_ptr<auto_mysql_stmt> stmt;
string_buffer wbuf;
for (int i = 0; i < num; ++i) {
const double tm1 = gettimeofday_double();
const int flags = 0;
......@@ -623,6 +625,20 @@ hstest_thread::test_9(int test_num)
// TODO: moreflds
} else if (ssps) {
//
} else if (use_in) {
wbuf.clear();
char *p = wbuf.make_space(1024);
int len = snprintf(p, 1024, "select %s from hstest_table1 where k in ('%d'", flds.c_str(), k);
wbuf.space_wrote(len);
for (int j = 1; j < use_in; ++j) {
/* generate more key */
drand48_r(&randbuf, &kf);
k = int(kf * tablesize);
p = wbuf.make_space(1024);
int len = snprintf(p, 1024, ", '%d'", k);
wbuf.space_wrote(len);
}
wbuf.append_literal(")");
} else {
buf_query_len = snprintf(buf_query, sizeof(buf_query),
"select %s from hstest_table1 where k = '%d'", flds.c_str(), k);
......@@ -651,6 +667,8 @@ hstest_thread::test_9(int test_num)
}
r = mysql_stmt_execute(*stmt);
// fprintf(stderr, "stmt exec\n");
} else if (use_in) {
r = mysql_real_query(db, wbuf.begin(), wbuf.size());
} else {
r = mysql_real_query(db, buf_query, buf_query_len);
// fprintf(stderr, "real query\n");
......@@ -694,7 +712,7 @@ hstest_thread::test_9(int test_num)
num_flds = mysql_num_fields(res);
MYSQL_ROW row = 0;
while ((row = mysql_fetch_row(res)) != 0) {
got_data = 1;
got_data += 1;
unsigned long *const lengths = mysql_fetch_lengths(res);
if (verbose >= 2) {
for (unsigned int i = 0; i < num_flds; ++i) {
......@@ -706,7 +724,10 @@ hstest_thread::test_9(int test_num)
}
}
} else {
got_data = 1;
MYSQL_ROW row = 0;
while ((row = mysql_fetch_row(res)) != 0) {
got_data += 1;
}
}
} else {
if (mysql_field_count(db) == 0) {
......@@ -730,7 +751,7 @@ hstest_thread::test_9(int test_num)
if (err == 0) {
++io_success_count;
if (num_affected_rows > 0 || got_data > 0) {
++op_success_count;
op_success_count += got_data;
} else {
if (verbose >= 1) {
fprintf(stderr, "k=%d numaff=%u gotdata=%d\n",
......@@ -779,6 +800,7 @@ hstest_thread::test_10(int test_num)
const std::string table = arg.sh.conf.get_str("table", "hstest_table1");
const std::string index = arg.sh.conf.get_str("index", "PRIMARY");
const std::string field = arg.sh.conf.get_str("field", "v");
const int use_in = arg.sh.conf.get_int("in", 0);
const std::string moreflds_prefix = arg.sh.conf.get_str(
"moreflds_prefix", "column0123456789_");
const int dump = arg.sh.dump;
......@@ -789,8 +811,8 @@ hstest_thread::test_10(int test_num)
snprintf(sbuf, sizeof(sbuf), ",%s%d", moreflds_prefix.c_str(), i);
moreflds_str += std::string(sbuf);
}
char wbuf[16384], rbuf[16384];
int wbuflen = 0;
string_buffer wbuf;
char rbuf[16384];
for (size_t i = 0; i < arg.sh.loop; ++i) {
int len = 0, rlen = 0, wlen = 0;
#if 0
......@@ -801,15 +823,18 @@ hstest_thread::test_10(int test_num)
fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
return;
}
len = snprintf(wbuf, sizeof(wbuf),
char *wp = wbuf.make_space(1024);
len = snprintf(wp, 1024,
"P\t1\t%s\t%s\tPRIMARY\t%s%s\n", dbname.c_str(), table.c_str(),
field.c_str(), moreflds_str.c_str());
/* pst_num, db, table, index, retflds */
wlen = write(fd.get(), wbuf, len);
wbuf.space_wrote(len);
wlen = write(fd.get(), wbuf.begin(), len);
if (len != wlen) {
fprintf(stderr, "write: %d %d\n", len, wlen);
return;
}
wbuf.clear();
rlen = read(fd.get(), rbuf, sizeof(rbuf));
if (rlen <= 0 || rbuf[rlen - 1] != '\n') {
fprintf(stderr, "read: rlen=%d errno=%d\n", rlen, errno);
......@@ -824,7 +849,6 @@ hstest_thread::test_10(int test_num)
const double tm1 = gettimeofday_double();
for (size_t j = 0; j < arg.sh.pipe; ++j) {
int k = 0, v = 0;
wbuflen = 0;
{
while (true) {
double kf = 0, vf = 0;
......@@ -832,19 +856,6 @@ hstest_thread::test_10(int test_num)
drand48_r(&randbuf, &vf);
k = int(kf * tablesize) + firstkey;
v = int(vf * tablesize) + firstkey;
// k = rand_r(&seed);
// v = rand_r(&seed); /* unused */
#if 0
if (tablesize != 0) {
k &= tablesize;
}
#endif
if (op == 'G') {
wbuflen = snprintf(wbuf, sizeof(wbuf), "1\t=\t1\t%d\n", k);
} else if (op == 'U') {
wbuflen = snprintf(wbuf, sizeof(wbuf),
"1\t=\t1\t%d\t1\t0\tU\t%d_%d%s\n", k, v, k, suffix.c_str());
}
if (k - firstkey < arg.sh.keygen_size) {
volatile char *const ptr = arg.sh.keygen + (k - firstkey);
// int oldv = __sync_fetch_and_or(ptr, 1);
......@@ -864,15 +875,42 @@ hstest_thread::test_10(int test_num)
continue;
}
}
size_t len = 0;
if (op == 'G') {
if (use_in) {
char *wp = wbuf.make_space(1024);
len = snprintf(wp, 1024, "1\t=\t1\t\t%d\t0\t@\t0\t%d\t%d",
use_in, use_in, k);
wbuf.space_wrote(len);
for (int j = 1; j < use_in; ++j) {
drand48_r(&randbuf, &kf);
k = int(kf * tablesize) + firstkey;
char *wp = wbuf.make_space(1024);
len = snprintf(wp, 1024, "\t%d", k);
wbuf.space_wrote(len);
}
wbuf.append_literal("\n");
} else {
char *wp = wbuf.make_space(1024);
len = snprintf(wp, 1024, "1\t=\t1\t%d\n", k);
wbuf.space_wrote(len);
}
} else if (op == 'U') {
char *wp = wbuf.make_space(1024);
len = snprintf(wp, 1024,
"1\t=\t1\t%d\t1\t0\tU\t%d_%d%s\n", k, v, k, suffix.c_str());
wbuf.space_wrote(len);
}
break;
}
}
wlen = write(fd.get(), wbuf, wbuflen);
if (wlen != wbuflen) {
fprintf(stderr, "write: %d %d\n", wbuflen, wlen);
return;
}
}
wlen = write(fd.get(), wbuf.begin(), wbuf.size());
if ((size_t) wlen != wbuf.size()) {
fprintf(stderr, "write: %d %d\n", (int)wbuf.size(), wlen);
return;
}
wbuf.clear();
size_t read_cnt = 0;
size_t read_pos = 0;
while (read_cnt < arg.sh.pipe) {
......@@ -922,7 +960,7 @@ hstest_thread::test_10(int test_num)
++op_success_count;
arg.sh.increment_count();
if (arg.sh.dump && arg.sh.pipe == 1) {
fwrite(wbuf, wbuflen, 1, stderr);
fwrite(wbuf.begin(), wbuf.size(), 1, stderr);
}
}
}
......
......@@ -13,6 +13,12 @@ AC_PROG_CXX
AC_PROG_CPP
AC_PROG_LIBTOOL
ac_mysql_debug=
AC_ARG_ENABLE(mysql-debug,
[AS_HELP_STRING([--enable-mysql-debug], [specify whether MySQL is build with DBUG_ON])],[ac_mysql_debug="$enableval"],[ac_mysql_debug=no])
AC_MSG_CHECKING([if --enable-mysql-debug is specified])
AC_MSG_RESULT($ac_mysql_debug)
AC_DEFUN([CONFIG_OPTION_MYSQL],[
AC_MSG_CHECKING([mysql source])
......@@ -66,8 +72,12 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
fi
MYSQL_CFLAGS_ADD=`"$ac_mysql_config" --cflags`
MYSQL_CFLAGS="$MYSQL_CFLAGS $MYSQL_CFLAGS_ADD -DFORCE_DBUG_OFF"
# FIXME
MYSQL_CFLAGS="$MYSQL_CFLAGS $MYSQL_CFLAGS_ADD"
if test "$ac_mysql_debug" = "yes"; then
MYSQL_CFLAGS="$MYSQL_CFLAGS -DDBUG_ON -DENABLED_DEBUG_SYNC"
else
MYSQL_CFLAGS="$MYSQL_CFLAGS -DDBUG_OFF"
fi
AC_SUBST(MYSQL_CFLAGS)
MYSQL_BIN_VERSION=`"$ac_mysql_config" --version`
......
......@@ -80,8 +80,20 @@ handlersocket_accept_balance (default = 0, min = 0, max = 10000)
handlersocket_wrlock_timeout (default = 12, min = 0, max = 3600)
Specify the lock timeout in seconds. When a write request is
performed, handlersocket locks an advisory lock named
performed, handlersocket acquires an advisory lock named
'handlersocket_wr'. This option sets the timeout for the
locking.
-----------------------------------------------------------------
handlersocket_plain_secret (default = '')
When this option is specified, a plain-text authentication is
enabled for the listener for read requests. This option
specifies the secret key for the authentication.
-----------------------------------------------------------------
handlersocket_plain_secret_wr (default = '')
This option specifies the secret key for the listener for write
requests.
......@@ -11,7 +11,7 @@ Basic syntax
distinguish NULL from an empty string, as most DBMs does so.
- NULL is expressed as a single NUL(0x00).
- An encoded string is a string with the following encoding rules.
- Characters in the range [0x10 - 0xff] are not encoded.
- Characters in the range [0x10 - 0xff] are encoded as itselves.
- A character in the range [0x00 - 0x0f] is prefixed by 0x01 and
shifted by 0x40. For example, 0x03 is encoded as 0x01 0x43.
- Note that a string can be empty. A continuation of 0x09 0x09 means that
......@@ -33,12 +33,14 @@ Request and Response
The 'open_index' request has the following syntax.
P <indexid> <dbname> <tablename> <indexname> <columns>
P <indexid> <dbname> <tablename> <indexname> <columns> [<fcolumns>]
- <indexid> is a number in decimal.
- <dbname>, <tablename>, and <indexname> are strings. To open the primary
key, use PRIMARY as <indexname>.
- <columns> is a comma-separated list of column names.
- <fcolumns> is a comma-separated list of column names. This parameter is
optional.
Once an 'open_index' request is issued, the HandlerSocket plugin opens the
specified index and keep it open until the client connection is closed. Each
......@@ -51,8 +53,20 @@ For efficiency, keep <indexid> small as far as possible.
Getting data
The 'find' request has the following syntax.
<indexid> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER ...]
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset>
LIM is a sequence of the following parameters.
<limit> <offset>
IN is a sequence of the following parameters.
@ <icol> <ivlen> <iv1> ... <ivn>
FILETER is a sequence of the following parameters.
<ftyp> <fop> <fcol> <fval>
- <indexid> is a number. This number must be an <indexid> specified by a
'open_index' request executed previously on the same connection.
......@@ -60,30 +74,53 @@ The 'find' request has the following syntax.
HandlerSocket supports '=', '>', '>=', '<', and '<='.
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This
must be smaller than or equal to the number of index columns specified by
specified by the corresponding 'open_index' request.
the <columns> parameter of the corresponding 'open_index' request.
- <v1> ... <vn> specify the index column values to fetch.
- <limit> and <offset> are numbers. These parameters can be omitted. When
omitted, it works as if 1 and 0 are specified.
- LIM is optional. <limit> and <offset> are numbers. When omitted, it works
as if 1 and 0 are specified. These parameter works like LIMIT of SQL.
These values don't include the number of records skipped by a filter.
- IN is optional. It works like WHERE ... IN syntax of SQL. <icol> must be
smaller than or equal to the number of index columns specified by the
<columns> parameter of the corresponding 'open_index' request. If IN is
specified in a find request, the <icol>-th parameter value of <v1> ...
<vn> is ignored.
smaller than or equal to the number of index columns specified by the
- FILTERs are optional. A FILTER specifies a filter. <ftyp> is either 'F'
(filter) or 'W' (while). <fop> specifies the comparison operation to use.
<fcol> must be smaller than or equal to the number of columns specified by
the <fcolumns> parameter of the corresponding 'open_index' request.
Multiple filters can be specified, and work as the logical AND of them.
The difference of 'F' and 'W' is that, when a record does not meet the
specified condition, 'F' simply skips the record, and 'W' stops the loop.
----------------------------------------------------------------------------
Updating/Deleting data
The 'find_modify' request has the following syntax.
<indexid> <op> <vlen> <v1> ... <vn> <limit> <offset> <mop> <m1> ... <mk>
<indexid> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER ...] MOD
MOD is a sequence of the following parameters.
<mop> <m1> ... <mk>
- <mop> is either 'U' (update) or 'D' (delete).
- <mop> is 'U' (update), '+' (increment), '-' (decrement), 'D' (delete),
'U?', '+?', '-?', or 'D?'. If the '?' suffix is specified, it returns
the contents of the records before modification (as if it's a 'find'
request), instead of the number of modified records.
- <m1> ... <mk> specifies the column values to set. The length of <m1> ...
<mk> must be smaller than or equal to the length of <columns> specified by
the corresponding 'open_index' request. If <mop> is 'D', these parameters
are ignored.
are ignored. If <mop> is '+' or '-', values must be numeric. If <mop> is
'-' and it attempts to change column values from negative to positive or
positive to negative, it is not modified.
----------------------------------------------------------------------------
Inserting data
The 'insert' request has the following syntax.
<indexid> '+' <vlen> <v1> ... <vn>
<indexid> + <vlen> <v1> ... <vn>
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This
must be smaller than or equal to the length of <columns> specified by the
......@@ -91,6 +128,19 @@ The 'insert' request has the following syntax.
- <v1> ... <vn> specify the column values to set. For columns not in
<columns>, the default values for each column are set.
----------------------------------------------------------------------------
Authentication
The 'auth' request has the following syntax.
A <atyp> <akey>
- <atyp> must be '1'
- An 'auth' request succeeds iff <akey> is the correct secret specified by
the 'handlersocket_plain_secret' or 'handlersocket_plain_secret_rw'.
- If an authentication is enabled for a listener, any other requests on a
connection fail before an 'auth' request succeeded on the connection.
----------------------------------------------------------------------------
Response syntax
......
......@@ -62,6 +62,7 @@ struct dbcallback_i {
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const = 0;
virtual void dbcb_resp_short(uint32_t code, const char *msg) = 0;
virtual void dbcb_resp_short_num(uint32_t code, uint32_t value) = 0;
virtual void dbcb_resp_short_num64(uint32_t code, uint64_t value) = 0;
virtual void dbcb_resp_begin(size_t num_flds) = 0;
virtual void dbcb_resp_entry(const char *fld, size_t fldlen) = 0;
virtual void dbcb_resp_end() = 0;
......@@ -81,6 +82,17 @@ struct record_filter {
record_filter() : filter_type(record_filter_type_skip), ff_offset(0) { }
};
struct cmd_open_args {
size_t pst_id;
const char *dbn;
const char *tbl;
const char *idx;
const char *retflds;
const char *filflds;
cmd_open_args() : pst_id(0), dbn(0), tbl(0), idx(0), retflds(0),
filflds(0) { }
};
struct cmd_exec_args {
const prep_stmt *pst;
string_ref op;
......@@ -91,8 +103,11 @@ struct cmd_exec_args {
string_ref mod_op;
const string_ref *uvals; /* size must be pst->retfieelds.size() */
const record_filter *filters;
int invalues_keypart;
const string_ref *invalues;
size_t invalueslen;
cmd_exec_args() : pst(0), kvals(0), kvalslen(0), limit(0), skip(0),
uvals(0), filters(0) { }
uvals(0), filters(0), invalues_keypart(-1), invalues(0), invalueslen(0) { }
};
struct dbcontext_i {
......@@ -108,11 +123,8 @@ struct dbcontext_i {
virtual void close_tables_if() = 0;
virtual void table_addref(size_t tbl_id) = 0; /* TODO: hide */
virtual void table_release(size_t tbl_id) = 0; /* TODO: hide */
virtual void cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn,
const char *tbl, const char *idx, const char *retflds,
const char *filflds) = 0;
virtual void cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
= 0;
virtual void cmd_open(dbcallback_i& cb, const cmd_open_args& args) = 0;
virtual void cmd_exec(dbcallback_i& cb, const cmd_exec_args& args) = 0;
virtual void set_statistics(size_t num_conns, size_t num_active) = 0;
};
......
......@@ -27,6 +27,7 @@
#define DBG_FD(x)
#define DBG_TR(x)
#define DBG_EP(x)
#define DBG_MULTI(x)
/* TODO */
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(MSG_NOSIGNAL)
......@@ -40,13 +41,15 @@ struct dbconnstate {
string_buffer writebuf;
std::vector<prep_stmt> prep_stmts;
size_t resp_begin_pos;
size_t find_nl_pos;
void reset() {
readbuf.clear();
writebuf.clear();
prep_stmts.clear();
resp_begin_pos = 0;
find_nl_pos = 0;
}
dbconnstate() : resp_begin_pos(0) { }
dbconnstate() : resp_begin_pos(0), find_nl_pos(0) { }
};
struct hstcpsvr_conn;
......@@ -78,6 +81,7 @@ struct hstcpsvr_conn : public dbcallback_i {
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const;
virtual void dbcb_resp_short(uint32_t code, const char *msg);
virtual void dbcb_resp_short_num(uint32_t code, uint32_t value);
virtual void dbcb_resp_short_num64(uint32_t code, uint64_t value);
virtual void dbcb_resp_begin(size_t num_flds);
virtual void dbcb_resp_entry(const char *fld, size_t fldlen);
virtual void dbcb_resp_end();
......@@ -205,6 +209,15 @@ hstcpsvr_conn::dbcb_resp_short_num(uint32_t code, uint32_t value)
cstate.writebuf.append_literal("\n");
}
void
hstcpsvr_conn::dbcb_resp_short_num64(uint32_t code, uint64_t value)
{
write_ui32(cstate.writebuf, code);
cstate.writebuf.append_literal("\t1\t");
write_ui64(cstate.writebuf, value);
cstate.writebuf.append_literal("\n");
}
void
hstcpsvr_conn::dbcb_resp_begin(size_t num_flds)
{
......@@ -256,6 +269,7 @@ struct hstcpsvr_worker : public hstcpsvr_worker_i, private noncopyable {
#endif
bool accept_enabled;
int accept_balance;
std::vector<string_ref> invalues_work;
std::vector<record_filter> filters_work;
private:
int run_one_nb();
......@@ -385,6 +399,7 @@ hstcpsvr_worker::run_one_nb()
vshared.shutdown = 1;
} else if (ch == '/') {
conn.cstate.readbuf.clear();
conn.cstate.find_nl_pos = 0;
conn.cstate.writebuf.clear();
conn.read_finished = true;
conn.write_finished = true;
......@@ -533,6 +548,7 @@ hstcpsvr_worker::run_one_ep()
vshared.shutdown = 1;
} else if (ch == '/') {
conn->cstate.readbuf.clear();
conn->cstate.find_nl_pos = 0;
conn->cstate.writebuf.clear();
conn->read_finished = true;
conn->write_finished = true;
......@@ -641,19 +657,24 @@ hstcpsvr_worker::run_one_ep()
void
hstcpsvr_worker::execute_lines(hstcpsvr_conn& conn)
{
DBG_MULTI(int cnt = 0);
dbconnstate& cstate = conn.cstate;
char *buf_end = cstate.readbuf.end();
char *line_begin = cstate.readbuf.begin();
char *find_pos = line_begin + cstate.find_nl_pos;
while (true) {
char *const nl = memchr_char(line_begin, '\n', buf_end - line_begin);
char *const nl = memchr_char(find_pos, '\n', buf_end - find_pos);
if (nl == 0) {
break;
}
char *const lf = (line_begin != nl && nl[-1] == '\r') ? nl - 1 : nl;
DBG_MULTI(cnt++);
execute_line(line_begin, lf, conn);
line_begin = nl + 1;
find_pos = line_begin = nl + 1;
}
cstate.readbuf.erase_front(line_begin - cstate.readbuf.begin());
cstate.find_nl_pos = cstate.readbuf.size();
DBG_MULTI(fprintf(stderr, "cnt=%d\n", cnt));
}
void
......@@ -721,8 +742,14 @@ hstcpsvr_worker::do_open_index(char *start, char *finish, hstcpsvr_conn& conn)
idxname_end[0] = 0;
retflds_end[0] = 0;
filflds_end[0] = 0;
return dbctx->cmd_open_index(conn, pst_id, dbname_begin, tblname_begin,
idxname_begin, retflds_begin, filflds_begin);
cmd_open_args args;
args.pst_id = pst_id;
args.dbn = dbname_begin;
args.tbl = tblname_begin;
args.idx = idxname_begin;
args.retflds = retflds_begin;
args.filflds = filflds_begin;
return dbctx->cmd_open(conn, args);
}
void
......@@ -741,7 +768,8 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
args.op = string_ref(op_begin, op_end);
skip_one(start, finish);
const uint32_t fldnum = read_ui32(start, finish);
string_ref flds[fldnum]; /* GNU */
string_ref *const flds = DENA_ALLOCA_ALLOCATE(string_ref, fldnum);
auto_alloca_free<string_ref> flds_autofree(flds);
args.kvals = flds;
args.kvalslen = fldnum;
for (size_t i = 0; i < fldnum; ++i) {
......@@ -765,10 +793,39 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
args.skip = read_ui32(start, finish);
if (start == finish) {
/* simple query */
return dbctx->cmd_exec_on_index(conn, args);
return dbctx->cmd_exec(conn, args);
}
/* has filters or modops */
/* has more options */
skip_one(start, finish);
/* in-clause */
if (start[0] == '@') {
read_token(start, finish); /* '@' */
skip_one(start, finish);
args.invalues_keypart = read_ui32(start, finish);
skip_one(start, finish);
args.invalueslen = read_ui32(start, finish);
if (args.invalueslen <= 0) {
return conn.dbcb_resp_short(2, "invalueslen");
}
if (invalues_work.size() < args.invalueslen) {
invalues_work.resize(args.invalueslen);
}
args.invalues = &invalues_work[0];
for (uint32_t i = 0; i < args.invalueslen; ++i) {
skip_one(start, finish);
char *const invalue_begin = start;
read_token(start, finish);
char *const invalue_end = start;
char *wp = invalue_begin;
unescape_string(wp, invalue_begin, invalue_end);
invalues_work[i] = string_ref(invalue_begin, wp - invalue_begin);
}
skip_one(start, finish);
}
if (start == finish) {
/* no more options */
return dbctx->cmd_exec(conn, args);
}
/* filters */
size_t filters_count = 0;
while (start != finish && (start[0] == 'W' || start[0] == 'F')) {
......@@ -823,7 +880,7 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
}
if (start == finish) {
/* no modops */
return dbctx->cmd_exec_on_index(conn, args);
return dbctx->cmd_exec(conn, args);
}
/* has modops */
char *const mod_op_begin = start;
......@@ -831,7 +888,8 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
char *const mod_op_end = start;
args.mod_op = string_ref(mod_op_begin, mod_op_end);
const size_t num_uvals = args.pst->get_ret_fields().size();
string_ref uflds[num_uvals]; /* GNU */
string_ref *const uflds = DENA_ALLOCA_ALLOCATE(string_ref, num_uvals);
auto_alloca_free<string_ref> uflds_autofree(uflds);
for (size_t i = 0; i < num_uvals; ++i) {
skip_one(start, finish);
char *const f_begin = start;
......@@ -848,7 +906,7 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
}
}
args.uvals = uflds;
return dbctx->cmd_exec_on_index(conn, args);
return dbctx->cmd_exec(conn, args);
}
void
......@@ -871,7 +929,7 @@ hstcpsvr_worker::do_authorization(char *start, char *finish,
char *wp = key_begin;
unescape_string(wp, key_begin, key_end);
if (authtype_len != 1 || authtype_begin[0] != '1') {
return conn.dbcb_resp_short(2, "authtype");
return conn.dbcb_resp_short(3, "authtype");
}
if (cshared.plain_secret.size() == key_len &&
memcmp(cshared.plain_secret.data(), key_begin, key_len) == 0) {
......
......@@ -17,6 +17,7 @@
#define MYSQL_SERVER 1
#include <my_config.h>
#include <mysql_version.h>
#if MYSQL_VERSION_ID >= 50505
......
......@@ -33,5 +33,32 @@ typedef std::allocator<int> allocator_type;
typedef std::allocator<int> allocator_type;
#endif
#if 1
#define DENA_ALLOCA_ALLOCATE(typ, len) \
static_cast<typ *>(alloca((len) * sizeof(typ)))
#define DENA_ALLOCA_FREE(x)
#else
#define DENA_ALLOCA_ALLOCATE(typ, len) \
static_cast<typ *>(malloc((len) * sizeof(typ)))
#define DENA_ALLOCA_FREE(x) free(x)
#endif
namespace dena {
template <typename T> struct auto_alloca_free {
auto_alloca_free(T *value) : value(value) { }
~auto_alloca_free() {
/* no-op if alloca() is used */
DENA_ALLOCA_FREE(value);
}
private:
auto_alloca_free(const auto_alloca_free&);
auto_alloca_free& operator =(const auto_alloca_free&);
private:
T *value;
};
};
#endif
......@@ -12,7 +12,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include "util.hpp"
namespace dena {
......@@ -33,7 +33,6 @@ struct auto_addrinfo : private noncopyable {
int family = AF_UNSPEC, int socktype = SOCK_STREAM, int protocol = 0) {
reset();
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = flags;
hints.ai_family = family;
hints.ai_socktype = socktype;
......
......@@ -106,8 +106,18 @@ read_ui32(char *& start, char *finish)
void
write_ui32(string_buffer& buf, uint32_t v)
{
char *wp = buf.make_space(32);
int len = snprintf(wp, 32, "%u", v);
char *wp = buf.make_space(12);
int len = snprintf(wp, 12, "%u", v);
if (len > 0) {
buf.space_wrote(len);
}
}
void
write_ui64(string_buffer& buf, uint64_t v)
{
char *wp = buf.make_space(22);
int len = snprintf(wp, 22, "%llu", static_cast<unsigned long long>(v));
if (len > 0) {
buf.space_wrote(len);
}
......
......@@ -25,6 +25,7 @@ bool unescape_string(string_buffer& ar, const char *start, const char *finish);
uint32_t read_ui32(char *& start, char *finish);
void write_ui32(string_buffer& buf, uint32_t v);
void write_ui64(string_buffer& buf, uint64_t v);
inline bool
is_null_expression(const char *start, const char *finish)
......
......@@ -31,21 +31,12 @@ struct hstcpcli : public hstcpcli_i, private noncopyable {
virtual bool stable_point();
virtual void request_buf_open_index(size_t pst_id, const char *dbn,
const char *tbl, const char *idx, const char *retflds, const char *filflds);
#if 0
virtual void request_buf_find(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip);
virtual void request_buf_insert(size_t pst_id, const string_ref *fvs,
size_t fvslen);
virtual void request_buf_update(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref *mvs, size_t mvslen);
virtual void request_buf_delete(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip);
#endif
virtual void request_buf_auth(const char *secret, const char *typ);
virtual void request_buf_exec_generic(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
const hstcpcli_filter *fils, size_t filslen);
const hstcpcli_filter *fils, size_t filslen, int invalues_keypart,
const string_ref *invalues, size_t invalueslen);
virtual int request_send();
virtual int response_recv(size_t& num_flds_r);
virtual const string_ref *get_next_row();
......@@ -196,6 +187,27 @@ hstcpcli::request_buf_open_index(size_t pst_id, const char *dbn,
++num_req_bufd;
}
void
hstcpcli::request_buf_auth(const char *secret, const char *typ)
{
if (num_req_sent > 0 || num_req_rcvd > 0) {
close();
set_error(-1, "request_buf_auth: protocol out of sync");
return;
}
if (typ == 0) {
typ = "1";
}
const string_ref typ_ref(typ, strlen(typ));
const string_ref secret_ref(secret, strlen(secret));
writebuf.append_literal("A\t");
writebuf.append(typ_ref.begin(), typ_ref.end());
writebuf.append_literal("\t");
writebuf.append(secret_ref.begin(), secret_ref.end());
writebuf.append_literal("\n");
++num_req_bufd;
}
namespace {
void
......@@ -218,7 +230,8 @@ void
hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
const hstcpcli_filter *fils, size_t filslen)
const hstcpcli_filter *fils, size_t filslen, int invalues_keypart,
const string_ref *invalues, size_t invalueslen)
{
if (num_req_sent > 0 || num_req_rcvd > 0) {
close();
......@@ -234,13 +247,26 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
const string_ref& kv = kvs[i];
append_delim_value(writebuf, kv.begin(), kv.end());
}
if (limit != 0 || skip != 0 || mod_op.size() != 0 || filslen != 0) {
if (limit != 0 || skip != 0 || invalues_keypart >= 0 ||
mod_op.size() != 0 || filslen != 0) {
/* has more option */
writebuf.append_literal("\t");
append_uint32(writebuf, limit); // FIXME size_t ?
if (skip != 0 || mod_op.size() != 0 || filslen != 0) {
if (skip != 0 || invalues_keypart >= 0 ||
mod_op.size() != 0 || filslen != 0) {
writebuf.append_literal("\t");
append_uint32(writebuf, skip); // FIXME size_t ?
}
if (invalues_keypart >= 0) {
writebuf.append_literal("\t@\t");
append_uint32(writebuf, invalues_keypart);
writebuf.append_literal("\t");
append_uint32(writebuf, invalueslen);
for (size_t i = 0; i < invalueslen; ++i) {
const string_ref& s = invalues[i];
append_delim_value(writebuf, s.begin(), s.end());
}
}
for (size_t i = 0; i < filslen; ++i) {
const hstcpcli_filter& f = fils[i];
writebuf.append_literal("\t");
......@@ -264,44 +290,6 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
++num_req_bufd;
}
#if 0
void
hstcpcli::request_buf_find(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip)
{
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
0, 0, 0);
}
void
hstcpcli::request_buf_insert(size_t pst_id, const string_ref *fvs,
size_t fvslen)
{
const string_ref insert_op("+", 1);
return request_buf_exec_generic(pst_id, insert_op, fvs, fvslen,
0, 0, string_ref(), 0, 0);
}
void
hstcpcli::request_buf_update(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref *mvs, size_t mvslen)
{
const string_ref modop_update("U", 1);
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
modop_update, mvs, mvslen);
}
void
hstcpcli::request_buf_delete(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip)
{
const string_ref modop_delete("D", 1);
return request_buf_exec_generic(pst_id, op, kvs, kvslen, limit, skip,
modop_delete, 0, 0);
}
#endif
int
hstcpcli::request_send()
{
......
......@@ -37,13 +37,16 @@ struct hstcpcli_i {
virtual void close() = 0;
virtual int reconnect() = 0;
virtual bool stable_point() = 0;
virtual void request_buf_auth(const char *secret, const char *typ) = 0;
virtual void request_buf_open_index(size_t pst_id, const char *dbn,
const char *tbl, const char *idx, const char *retflds,
const char *filflds = 0) = 0;
virtual void request_buf_exec_generic(size_t pst_id, const string_ref& op,
const string_ref *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen,
const hstcpcli_filter *fils = 0, size_t filslen = 0) = 0;
const hstcpcli_filter *fils = 0, size_t filslen = 0,
int invalues_keypart = -1, const string_ref *invalues = 0,
size_t invalueslen = 0) = 0; // FIXME: too long
virtual int request_send() = 0;
virtual int response_recv(size_t& num_flds_r) = 0;
virtual const string_ref *get_next_row() = 0;
......
......@@ -84,7 +84,7 @@ struct string_buffer : private noncopyable {
}
void space_wrote(size_t len) {
len = std::min(len, alloc_size - end_offset);
end_offset = std::min(end_offset + len, alloc_size);
end_offset += len;
}
template <size_t N>
void append_literal(const char (& str)[N]) {
......
......@@ -109,7 +109,7 @@ hv_to_strmap(HV *hv, std::map<std::string, std::string>& m_r)
static void
strrefarr_push_back(std::vector<dena::string_ref>& a_r, SV *sv)
{
if (sv == 0 || SvTYPE(sv) == SVt_NULL) {
if (sv == 0 || SvTYPE(sv) == SVt_NULL) { /* !SvPOK()? */
DBG(fprintf(stderr, "strrefarr_push_back: null\n"));
return a_r.push_back(dena::string_ref());
}
......@@ -135,7 +135,7 @@ av_to_strrefarr(AV *av, std::vector<dena::string_ref>& a_r)
static dena::string_ref
sv_get_string_ref(SV *sv)
{
if (sv == 0) {
if (sv == 0 || SvTYPE(sv) == SVt_NULL) { /* !SvPOK()? */
return dena::string_ref();
}
STRLEN vlen = 0;
......@@ -190,7 +190,8 @@ set_process_verbose_level(const std::map<std::string, std::string>& m)
static AV *
execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
int skip, const char *modop, AV *modvals, AV *filters)
int skip, const char *modop, AV *modvals, AV *filters, int invalues_keypart,
AV *invalues)
{
AV *retval = (AV *)&PL_sv_undef;
dena::hstcpcli_i *const ptr =
......@@ -198,6 +199,7 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
do {
std::vector<dena::string_ref> keyarr, mvarr;
std::vector<dena::hstcpcli_filter> farr;
std::vector<dena::string_ref> ivs;
av_to_strrefarr(keys, keyarr);
dena::string_ref modop_ref;
if (modop != 0) {
......@@ -207,9 +209,13 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
if (filters != 0) {
av_to_filters(filters, farr);
}
if (invalues_keypart >= 0 && invalues != 0) {
av_to_strrefarr(invalues, ivs);
}
ptr->request_buf_exec_generic(id, dena::string_ref(op, strlen(op)),
&keyarr[0], keyarr.size(), limit, skip, modop_ref, &mvarr[0],
mvarr.size(), &farr[0], farr.size());
mvarr.size(), &farr[0], farr.size(), invalues_keypart, &ivs[0],
ivs.size());
AV *const av = newAV();
retval = av;
if (ptr->request_send() != 0) {
......@@ -258,8 +264,10 @@ struct execute_arg {
const char *modop;
AV *modvals;
AV *filters;
int invalues_keypart;
AV *invalues;
execute_arg() : id(0), op(0), keys(0), limit(0), skip(0), modop(0),
modvals(0), filters(0) { }
modvals(0), filters(0), invalues_keypart(-1), invalues(0) { }
};
static AV *
......@@ -271,6 +279,7 @@ execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args)
for (size_t i = 0; i < num_args; ++i) {
std::vector<dena::string_ref> keyarr, mvarr;
std::vector<dena::hstcpcli_filter> farr;
std::vector<dena::string_ref> ivs;
const execute_arg& arg = args[i];
av_to_strrefarr(arg.keys, keyarr);
dena::string_ref modop_ref;
......@@ -281,10 +290,13 @@ execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args)
if (arg.filters != 0) {
av_to_filters(arg.filters, farr);
}
if (arg.invalues_keypart >= 0 && arg.invalues != 0) {
av_to_strrefarr(arg.invalues, ivs);
}
ptr->request_buf_exec_generic(arg.id,
dena::string_ref(arg.op, strlen(arg.op)), &keyarr[0], keyarr.size(),
arg.limit, arg.skip, modop_ref, &mvarr[0], mvarr.size(), &farr[0],
farr.size());
farr.size(), arg.invalues_keypart, &ivs[0], ivs.size());
}
AV *const retval = newAV();
/* sends the requests */
......@@ -419,6 +431,34 @@ CODE:
OUTPUT:
RETVAL
int
auth(obj, key, typ = 0)
SV *obj
const char *key
const char *typ
CODE:
RETVAL = 0;
dena::hstcpcli_i *const ptr =
reinterpret_cast<dena::hstcpcli_i *>(SvIV(SvRV(obj)));
do {
ptr->request_buf_auth(key, typ);
if (ptr->request_send() != 0) {
break;
}
size_t nflds = 0;
ptr->response_recv(nflds);
const int e = ptr->get_error_code();
DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
if (e >= 0) {
ptr->response_buf_remove();
}
DBG(fprintf(stderr, "errcode=%d\n", ptr->get_error_code()));
} while (0);
RETVAL = ptr->get_error_code();
OUTPUT:
RETVAL
int
open_index(obj, id, db, table, index, fields, ffields = 0)
SV *obj
......@@ -452,7 +492,7 @@ OUTPUT:
RETVAL
AV *
execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0, ivkeypart = -1, ivs = 0)
SV *obj
int id
const char *op
......@@ -462,12 +502,15 @@ execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
SV *mop
SV *mvs
SV *fils
int ivkeypart
SV *ivs
CODE:
const char *const mop_str = sv_get_strval(mop);
AV *const mvs_av = sv_get_arrval(mvs);
AV *const fils_av = sv_get_arrval(fils);
AV *const ivs_av = sv_get_arrval(ivs);
RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
fils_av);
fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL);
OUTPUT:
RETVAL
......@@ -500,9 +543,11 @@ CODE:
ag.modop = arr_get_strval(avtarget, argmax, 5);
ag.modvals = arr_get_arrval(avtarget, argmax, 6);
ag.filters = arr_get_arrval(avtarget, argmax, 7);
DBG(fprintf(stderr, "execute_multi3 %d: %d %s %p %d %d %s %p %p\n",
ag.invalues_keypart = arr_get_intval(avtarget, argmax, 8, -1);
ag.invalues = arr_get_arrval(avtarget, argmax, 9);
DBG(fprintf(stderr, "execute_multi3 %d: %d %s %p %d %d %s %p %p %d %p\n",
i, ag.id, ag.op, ag.keys, ag.limit, ag.skip, ag.modop, ag.modvals,
ag.filters));
ag.filters, ag.invalues_keypart, ag.invalues));
}
RETVAL = execute_multi_internal(obj, args, cmdsmax + 1);
sv_2mortal((SV *)RETVAL);
......@@ -510,7 +555,7 @@ OUTPUT:
RETVAL
AV *
execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0, ivkeypart = -1, ivs = 0)
SV *obj
int id
const char *op
......@@ -520,18 +565,21 @@ execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
SV *mop
SV *mvs
SV *fils
int ivkeypart
SV *ivs
CODE:
const char *const mop_str = sv_get_strval(mop);
AV *const mvs_av = sv_get_arrval(mvs);
AV *const fils_av = sv_get_arrval(fils);
AV *const ivs_av = sv_get_arrval(ivs);
RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
fils_av);
fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL);
OUTPUT:
RETVAL
AV *
execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0)
execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0, ivkeypart = -1, ivs = 0)
SV *obj
int id
const char *op
......@@ -540,16 +588,19 @@ execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0)
int skip
AV *modvals
SV *fils
int ivkeypart
SV *ivs
CODE:
AV *const fils_av = sv_get_arrval(fils);
AV *const ivs_av = sv_get_arrval(ivs);
RETVAL = execute_internal(obj, id, op, keys, limit, skip, "U",
modvals, fils_av);
modvals, fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL);
OUTPUT:
RETVAL
AV *
execute_delete(obj, id, op, keys, limit, skip, fils = 0)
execute_delete(obj, id, op, keys, limit, skip, fils = 0, ivkeypart = -1, ivs = 0)
SV *obj
int id
const char *op
......@@ -557,9 +608,13 @@ execute_delete(obj, id, op, keys, limit, skip, fils = 0)
int limit
int skip
SV *fils
int ivkeypart
SV *ivs
CODE:
AV *const fils_av = sv_get_arrval(fils);
RETVAL = execute_internal(obj, id, op, keys, limit, skip, "D", 0, fils_av);
AV *const ivs_av = sv_get_arrval(ivs);
RETVAL = execute_internal(obj, id, op, keys, limit, skip, "D", 0, fils_av,
ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL);
OUTPUT:
RETVAL
......@@ -570,7 +625,7 @@ execute_insert(obj, id, fvals)
int id
AV *fvals
CODE:
RETVAL = execute_internal(obj, id, "+", fvals, 0, 0, 0, 0, 0);
RETVAL = execute_internal(obj, id, "+", fvals, 0, 0, 0, 0, 0, -1, 0);
sv_2mortal((SV *)RETVAL);
OUTPUT:
RETVAL
......
......@@ -5,4 +5,4 @@ MANIFEST
ppport.h
README
t/HandlerSocket.t
lib/HandlerSocket.pm
lib/Net/HandlerSocket.pm
......@@ -21,6 +21,7 @@ sub init_conf {
$conf{user} = get_conf_env("MYSQLUSER", "root");
$conf{pass} = get_conf_env("MYSQLPASS", "");
$conf{hsport} = get_conf_env("HSPORT", 9998);
$conf{hspass} = get_conf_env("HSPASS", undef);
}
sub get_dbi_connection {
......@@ -52,6 +53,9 @@ sub get_hs_connection {
$port ||= $conf{hsport};
my $hsargs = { 'host' => $host, 'port' => $port };
my $conn = new Net::HandlerSocket($hsargs);
if (defined($conn) && defined($conf{hspass})) {
$conn->auth($conf{hspass});
}
return $conn;
}
......
#!/bin/bash
TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13";
TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23";
source ../common/compat.sh
......
HSINSERT
11 v1hs_0
12 v1hs_1
13 v1hs_2
14 v1hs_3
15 v1hs_4
16 v1hs_5
17 v1hs_6
18 v1hs_7
19 v1hs_8
20 v1hs_9
21 v1hs3_0
22 v1hs3_0
23 v1hs3_0
24 v1hs3_1
25 v1hs3_1
26 v1hs3_1
27 v1hs3_2
28 v1hs3_2
29 v1hs3_2
30 v1hs3_3
31 v1hs3_3
32 v1hs3_3
33 v1hs3_4
34 v1hs3_4
35 v1hs3_4
36 v1hs3_5
37 v1hs3_5
38 v1hs3_5
39 v1hs3_6
40 v1hs3_6
41 v1hs3_6
42 v1hs3_7
43 v1hs3_7
44 v1hs3_7
45 v1hs3_8
46 v1hs3_8
47 v1hs3_8
48 v1hs3_9
49 v1hs3_9
50 v1hs3_9
DUMP_TABLE
1 v1sql_0 v2sql_0
2 v1sql_1 v2sql_1
......
......@@ -47,6 +47,9 @@ for (my $i = 0; $i < $tablesize; ++$i) {
if ($err != 0) {
my $err_str = $r->[1];
print "$err $err_str\n";
} else {
my $id = $r->[1];
print "$id $v1\n";
}
}
# make sure that it works even when inserts are pipelined. these requests
......@@ -63,8 +66,11 @@ for (my $i = 0; $i < $tablesize; ++$i) {
for (my $i = 0; $i < 3; ++$i) {
my $err = $r->[$i]->[0];
if ($err != 0) {
my $err_str = $r->[1];
my $err_str = $r->[$i]->[1];
print "$err $err_str\n";
} else {
my $id = $r->[$i]->[1];
print "$id $v1\n";
}
}
}
......
DUMP_TABLE
0
1 0 A
2 01 AB
3 012 ABC
4 0123 ABCD
5 01234 ABCDE
6 012345 ABCDEF
7 0123456 ABCDEFG
8 01234567 ABCDEFGH
9 012345678 ABCDEFGHI
10 0123456789 ABCDEFGHIJ
11 01234567890 ABCDEFGHIJA
12 012345678901 ABCDEFGHIJAB
13 0123456789012 ABCDEFGHIJABC
14 01234567890123 ABCDEFGHIJABCD
15 012345678901234 ABCDEFGHIJABCDE
16 0123456789012345 ABCDEFGHIJABCDEF
17 01234567890123456 ABCDEFGHIJABCDEFG
18 012345678901234567 ABCDEFGHIJABCDEFGH
19 0123456789012345678 ABCDEFGHIJABCDEFGHI
20 01234567890123456789 ABCDEFGHIJABCDEFGHIJ
21 012345678901234567890 ABCDEFGHIJABCDEFGHIJA
22 0123456789012345678901 ABCDEFGHIJABCDEFGHIJAB
23 01234567890123456789012 ABCDEFGHIJABCDEFGHIJABC
24 012345678901234567890123 ABCDEFGHIJABCDEFGHIJABCD
25 0123456789012345678901234 ABCDEFGHIJABCDEFGHIJABCDE
26 01234567890123456789012345 ABCDEFGHIJABCDEFGHIJABCDEF
27 012345678901234567890123456 ABCDEFGHIJABCDEFGHIJABCDEFG
28 0123456789012345678901234567 ABCDEFGHIJABCDEFGHIJABCDEFGH
29 01234567890123456789012345678 ABCDEFGHIJABCDEFGHIJABCDEFGHI
30 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
31 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
32 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
33 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
34 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
35 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
36 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
37 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
38 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
39 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
40 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
41 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
42 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
43 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
44 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
45 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
46 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
47 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
48 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
49 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
PK 0
I1 0
I2 0
PK 1 0 A
I1 1 0 A
I2 1 0 A
PK 2 01 AB
I1 2 01 AB
I2 2 01 AB
PK 3 012 ABC
I1 3 012 ABC
I2 3 012 ABC
PK 4 0123 ABCD
I1 4 0123 ABCD
I2 4 0123 ABCD
PK 5 01234 ABCDE
I1 5 01234 ABCDE
I2 5 01234 ABCDE
PK 6 012345 ABCDEF
I1 6 012345 ABCDEF
I2 6 012345 ABCDEF
PK 7 0123456 ABCDEFG
I1 7 0123456 ABCDEFG
I2 7 0123456 ABCDEFG
PK 8 01234567 ABCDEFGH
I1 8 01234567 ABCDEFGH
I2 8 01234567 ABCDEFGH
PK 9 012345678 ABCDEFGHI
I1 9 012345678 ABCDEFGHI
I2 9 012345678 ABCDEFGHI
PK 10 0123456789 ABCDEFGHIJ
I1 10 0123456789 ABCDEFGHIJ
I2 10 0123456789 ABCDEFGHIJ
PK 11 01234567890 ABCDEFGHIJA
I1 11 01234567890 ABCDEFGHIJA
I2 11 01234567890 ABCDEFGHIJA
PK 12 012345678901 ABCDEFGHIJAB
I1 12 012345678901 ABCDEFGHIJAB
I2 12 012345678901 ABCDEFGHIJAB
PK 13 0123456789012 ABCDEFGHIJABC
I1 13 0123456789012 ABCDEFGHIJABC
I2 13 0123456789012 ABCDEFGHIJABC
PK 14 01234567890123 ABCDEFGHIJABCD
I1 14 01234567890123 ABCDEFGHIJABCD
I2 14 01234567890123 ABCDEFGHIJABCD
PK 15 012345678901234 ABCDEFGHIJABCDE
I1 15 012345678901234 ABCDEFGHIJABCDE
I2 15 012345678901234 ABCDEFGHIJABCDE
PK 16 0123456789012345 ABCDEFGHIJABCDEF
I1 16 0123456789012345 ABCDEFGHIJABCDEF
I2 16 0123456789012345 ABCDEFGHIJABCDEF
PK 17 01234567890123456 ABCDEFGHIJABCDEFG
I1 17 01234567890123456 ABCDEFGHIJABCDEFG
I2 17 01234567890123456 ABCDEFGHIJABCDEFG
PK 18 012345678901234567 ABCDEFGHIJABCDEFGH
I1 18 012345678901234567 ABCDEFGHIJABCDEFGH
I2 18 012345678901234567 ABCDEFGHIJABCDEFGH
PK 19 0123456789012345678 ABCDEFGHIJABCDEFGHI
I1 19 0123456789012345678 ABCDEFGHIJABCDEFGHI
I2 19 0123456789012345678 ABCDEFGHIJABCDEFGHI
PK 20 01234567890123456789 ABCDEFGHIJABCDEFGHIJ
I1 20 01234567890123456789 ABCDEFGHIJABCDEFGHIJ
I2 20 01234567890123456789 ABCDEFGHIJABCDEFGHIJ
PK 21 012345678901234567890 ABCDEFGHIJABCDEFGHIJA
I1 21 012345678901234567890 ABCDEFGHIJABCDEFGHIJA
I2 21 012345678901234567890 ABCDEFGHIJABCDEFGHIJA
PK 22 0123456789012345678901 ABCDEFGHIJABCDEFGHIJAB
I1 22 0123456789012345678901 ABCDEFGHIJABCDEFGHIJAB
I2 22 0123456789012345678901 ABCDEFGHIJABCDEFGHIJAB
PK 23 01234567890123456789012 ABCDEFGHIJABCDEFGHIJABC
I1 23 01234567890123456789012 ABCDEFGHIJABCDEFGHIJABC
I2 23 01234567890123456789012 ABCDEFGHIJABCDEFGHIJABC
PK 24 012345678901234567890123 ABCDEFGHIJABCDEFGHIJABCD
I1 24 012345678901234567890123 ABCDEFGHIJABCDEFGHIJABCD
I2 24 012345678901234567890123 ABCDEFGHIJABCDEFGHIJABCD
PK 25 0123456789012345678901234 ABCDEFGHIJABCDEFGHIJABCDE
I1 25 0123456789012345678901234 ABCDEFGHIJABCDEFGHIJABCDE
I2 25 0123456789012345678901234 ABCDEFGHIJABCDEFGHIJABCDE
PK 26 01234567890123456789012345 ABCDEFGHIJABCDEFGHIJABCDEF
I1 26 01234567890123456789012345 ABCDEFGHIJABCDEFGHIJABCDEF
I2 26 01234567890123456789012345 ABCDEFGHIJABCDEFGHIJABCDEF
PK 27 012345678901234567890123456 ABCDEFGHIJABCDEFGHIJABCDEFG
I1 27 012345678901234567890123456 ABCDEFGHIJABCDEFGHIJABCDEFG
I2 27 012345678901234567890123456 ABCDEFGHIJABCDEFGHIJABCDEFG
PK 28 0123456789012345678901234567 ABCDEFGHIJABCDEFGHIJABCDEFGH
I1 28 0123456789012345678901234567 ABCDEFGHIJABCDEFGHIJABCDEFGH
I2 28 0123456789012345678901234567 ABCDEFGHIJABCDEFGHIJABCDEFGH
PK 29 01234567890123456789012345678 ABCDEFGHIJABCDEFGHIJABCDEFGHI
I1 29 01234567890123456789012345678 ABCDEFGHIJABCDEFGHIJABCDEFGHI
I2 29 01234567890123456789012345678 ABCDEFGHIJABCDEFGHIJABCDEFGHI
PK 30 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
I1 30 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
I2 30 012345678901234567890123456789 ABCDEFGHIJABCDEFGHIJABCDEFGHIJ
#!/usr/bin/perl
# vim:sw=2:ai
# test for bugfix: commit/c88efe637f6a184b55d2bd8d060bda3e556572d8
# (some trailing bytes were dropped for varlen or nullable key fields)
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 50;
$dbh->do(
"create table $table (" .
"k int primary key, " .
"v1 varchar(30), " .
"v2 varchar(30), " .
"index i1(v1), index i2(v2, v1)) " .
"engine = myisam default charset = binary");
srand(999);
my %valmap = ();
my $sth = $dbh->prepare("insert into $table values (?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = $i;
my ($s1, $s2) = ("", "");
for (my $j = 0; $j < $i; ++$j) {
$s1 .= chr(48 + $j % 10);
$s2 .= chr(65 + $j % 10);
}
my $v1 = $s1;
my $v2 = $s2;
$sth->execute($k, $v1, $v2);
$valmap{$k} = [ $v1, $v2 ];
}
dump_table();
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
$hs->open_index(2, $dbname, $table, 'i1', 'k,v1,v2');
$hs->open_index(3, $dbname, $table, 'i2', 'k,v1,v2');
for (my $i = 0; $i <= 30; ++$i) {
my ($v1, $v2) = @{$valmap{$i}};
my ($rk, $rv1, $rv2);
my $r = $hs->execute_single(1, '=', [ $i ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "PK $rk $rv1 $rv2\n";
$r = $hs->execute_single(2, '=', [ $v1 ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I1 $rk $rv1 $rv2\n";
$r = $hs->execute_single(3, '=', [ $v2, $v1 ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I2 $rk $rv1 $rv2\n";
}
sub dump_table {
print "DUMP_TABLE\n";
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
for my $row (@$aref) {
my ($k, $v1, $v2) = @$row;
$v1 = "[null]" if !defined($v1);
$v2 = "[null]" if !defined($v2);
print "$k $v1 $v2\n";
# print "MISMATCH\n" if ($valmap{$k} ne $v);
}
}
This diff is collapsed.
#!/usr/bin/perl
# vim:sw=2:ai
# test for various numeric types
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use bigint;
use hstest;
my $numeric_types = [
[ 'TINYINT', -128, 127 ],
[ 'TINYINT UNSIGNED', 0, 255 ],
[ 'SMALLINT', -32768, 32768 ],
[ 'SMALLINT UNSIGNED', 0, 65535 ],
[ 'MEDIUMINT', -8388608, 8388607 ],
[ 'MEDIUMINT UNSIGNED', 0, 16777215 ],
[ 'INT', -2147483648, 2147483647 ],
[ 'INT UNSIGNED', 0, 4294967295 ],
[ 'BIGINT', -9223372036854775808, 9223372036854775807 ],
[ 'BIGINT UNSIGNED', 0, 18446744073709551615 ],
[ 'FLOAT', -32768, 32768 ],
[ 'DOUBLE', -2147483648, 2147483647 ],
];
my $table = 'hstesttbl';
my $dbh;
for my $rec (@$numeric_types) {
my ($typ, $minval, $maxval) = @$rec;
my @vals = ();
push(@vals, 0);
push(@vals, 1);
push(@vals, $maxval);
if ($minval != 0) {
push(@vals, -1);
push(@vals, $minval);
}
my $v1 = $minval;
my $v2 = $maxval;
for (my $i = 0; $i < 5; ++$i) {
$v1 /= 3;
$v2 /= 3;
if ($v1 != 0) {
push(@vals, int($v1));
}
push(@vals, int($v2));
}
@vals = sort { $a <=> $b } @vals;
print("TYPE $typ\n");
test_one($typ, \@vals);
print("\n");
}
sub test_one {
my ($typ, $values) = @_;
$dbh = hstest::init_testdb();
$dbh->do(
"create table $table (" .
"k $typ primary key, " .
"v1 varchar(512), " .
"v2 $typ, " .
"index i1(v1), index i2(v2, v1)) " .
"engine = myisam default charset = binary");
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
$hs->open_index(2, $dbname, $table, 'i1', 'k,v1,v2');
$hs->open_index(3, $dbname, $table, 'i2', 'k,v1,v2');
for my $k (@$values) {
my $kstr = 's' . $k;
$hs->execute_single(1, '+', [ $k, $kstr, $k ], 0, 0);
}
dump_table();
for my $k (@$values) {
my $kstr = 's' . $k;
my ($rk, $rv1, $rv2);
my $r;
$r = $hs->execute_single(1, '=', [ $k ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "PK[$k] $rk $rv1 $rv2\n";
$r = $hs->execute_single(2, '=', [ $kstr ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I1[$kstr] $rk $rv1 $rv2\n";
$r = $hs->execute_single(3, '=', [ $k, $kstr ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I2[$k, $kstr] $rk $rv1 $rv2\n";
$r = $hs->execute_single(3, '=', [ $k ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I2p[$k] $rk $rv1 $rv2\n";
}
}
sub dump_table {
print "DUMP_TABLE_BEGIN\n";
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
for my $row (@$aref) {
my ($k, $v1, $v2) = @$row;
$v1 = "[null]" if !defined($v1);
$v2 = "[null]" if !defined($v2);
print "$k $v1 $v2\n";
# print "MISMATCH\n" if ($valmap{$k} ne $v);
}
print "DUMP_TABLE_END\n";
}
TYPE DATE
DUMP_TABLE_BEGIN
0000-00-00 s0000-00-00 0000-00-00
2011-01-01 s2011-01-01 2011-01-01
9999-12-31 s9999-12-31 9999-12-31
DUMP_TABLE_END
PK[0000-00-00] 0000-00-00 s0000-00-00 0000-00-00
I1[s0000-00-00] 0000-00-00 s0000-00-00 0000-00-00
I2[0000-00-00, s0000-00-00] 0000-00-00 s0000-00-00 0000-00-00
I2p[0000-00-00] 0000-00-00 s0000-00-00 0000-00-00
PK[2011-01-01] 2011-01-01 s2011-01-01 2011-01-01
I1[s2011-01-01] 2011-01-01 s2011-01-01 2011-01-01
I2[2011-01-01, s2011-01-01] 2011-01-01 s2011-01-01 2011-01-01
I2p[2011-01-01] 2011-01-01 s2011-01-01 2011-01-01
PK[9999-12-31] 9999-12-31 s9999-12-31 9999-12-31
I1[s9999-12-31] 9999-12-31 s9999-12-31 9999-12-31
I2[9999-12-31, s9999-12-31] 9999-12-31 s9999-12-31 9999-12-31
I2p[9999-12-31] 9999-12-31 s9999-12-31 9999-12-31
TYPE DATETIME
DUMP_TABLE_BEGIN
0000-00-00 00:00:00 s0 0000-00-00 00:00:00
2011-01-01 18:30:25 s2011-01-01 18:30:25 2011-01-01 18:30:25
DUMP_TABLE_END
PK[0] 0000-00-00 00:00:00 s0 0000-00-00 00:00:00
I1[s0] 0000-00-00 00:00:00 s0 0000-00-00 00:00:00
I2[0, s0] 0000-00-00 00:00:00 s0 0000-00-00 00:00:00
I2p[0] 0000-00-00 00:00:00 s0 0000-00-00 00:00:00
PK[2011-01-01 18:30:25] 2011-01-01 18:30:25 s2011-01-01 18:30:25 2011-01-01 18:30:25
I1[s2011-01-01 18:30:25] 2011-01-01 18:30:25 s2011-01-01 18:30:25 2011-01-01 18:30:25
I2[2011-01-01 18:30:25, s2011-01-01 18:30:25] 2011-01-01 18:30:25 s2011-01-01 18:30:25 2011-01-01 18:30:25
I2p[2011-01-01 18:30:25] 2011-01-01 18:30:25 s2011-01-01 18:30:25 2011-01-01 18:30:25
TYPE TIME
DUMP_TABLE_BEGIN
00:00:00 s0 00:00:00
18:30:25 s18:30:25 18:30:25
DUMP_TABLE_END
PK[0] 00:00:00 s0 00:00:00
I1[s0] 00:00:00 s0 00:00:00
I2[0, s0] 00:00:00 s0 00:00:00
I2p[0] 00:00:00 s0 00:00:00
PK[18:30:25] 18:30:25 s18:30:25 18:30:25
I1[s18:30:25] 18:30:25 s18:30:25 18:30:25
I2[18:30:25, s18:30:25] 18:30:25 s18:30:25 18:30:25
I2p[18:30:25] 18:30:25 s18:30:25 18:30:25
TYPE YEAR(4)
DUMP_TABLE_BEGIN
1901 s1901 1901
2011 s2011 2011
2155 s2155 2155
DUMP_TABLE_END
PK[1901] 1901 s1901 1901
I1[s1901] 1901 s1901 1901
I2[1901, s1901] 1901 s1901 1901
I2p[1901] 1901 s1901 1901
PK[2011] 2011 s2011 2011
I1[s2011] 2011 s2011 2011
I2[2011, s2011] 2011 s2011 2011
I2p[2011] 2011 s2011 2011
PK[2155] 2155 s2155 2155
I1[s2155] 2155 s2155 2155
I2[2155, s2155] 2155 s2155 2155
I2p[2155] 2155 s2155 2155
#!/usr/bin/perl
# vim:sw=2:ai
# test for date/datetime types
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use bigint;
use hstest;
my $datetime_types = [
[ 'DATE', '0000-00-00', '2011-01-01', '9999-12-31' ],
[ 'DATETIME', 0, '2011-01-01 18:30:25' ],
[ 'TIME', 0, '18:30:25' ],
[ 'YEAR(4)', 1901, 2011, 2155 ],
# [ 'TIMESTAMP', 0, 999999999 ], # DOES NOT WORK YET
];
my $table = 'hstesttbl';
my $dbh;
for my $rec (@$datetime_types) {
my ($typ, @vals) = @$rec;
print("TYPE $typ\n");
test_one($typ, \@vals);
print("\n");
}
sub test_one {
my ($typ, $values) = @_;
$dbh = hstest::init_testdb();
$dbh->do(
"create table $table (" .
"k $typ primary key, " .
"v1 varchar(512), " .
"v2 $typ, " .
"index i1(v1), index i2(v2, v1)) " .
"engine = myisam default charset = binary");
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
$hs->open_index(2, $dbname, $table, 'i1', 'k,v1,v2');
$hs->open_index(3, $dbname, $table, 'i2', 'k,v1,v2');
for my $k (@$values) {
my $kstr = 's' . $k;
$hs->execute_single(1, '+', [ $k, $kstr, $k ], 0, 0);
}
dump_table();
for my $k (@$values) {
my $kstr = 's' . $k;
my ($rk, $rv1, $rv2);
my $r;
$r = $hs->execute_single(1, '=', [ $k ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "PK[$k] $rk $rv1 $rv2\n";
$r = $hs->execute_single(2, '=', [ $kstr ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I1[$kstr] $rk $rv1 $rv2\n";
$r = $hs->execute_single(3, '=', [ $k, $kstr ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I2[$k, $kstr] $rk $rv1 $rv2\n";
$r = $hs->execute_single(3, '=', [ $k ], 1, 0);
shift(@$r);
($rk, $rv1, $rv2) = @$r;
print "I2p[$k] $rk $rv1 $rv2\n";
}
}
sub dump_table {
print "DUMP_TABLE_BEGIN\n";
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
for my $row (@$aref) {
my ($k, $v1, $v2) = @$row;
$v1 = "[null]" if !defined($v1);
$v2 = "[null]" if !defined($v2);
print "$k $v1 $v2\n";
# print "MISMATCH\n" if ($valmap{$k} ne $v);
}
print "DUMP_TABLE_END\n";
}
#!/usr/bin/perl
# vim:sw=2:ai
# test for string types
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use bigint;
use hstest;
my $string_types = [
[ 'CHAR(10)', undef, 1, 2, 5, 10 ],
[ 'VARCHAR(10)', undef, 1, 2, 5, 10 ],
[ 'BINARY(10)', undef, 1, 2, 5, 10 ],
[ 'VARBINARY(10)', undef, 1, 2, 5, 10 ],
[ 'CHAR(255)', undef, 1, 2, 5, 10, 100, 200, 255 ],
[ 'VARCHAR(255)', undef, 1, 2, 5, 10, 100, 200, 255 ],
[ 'VARCHAR(511)', undef, 1, 2, 5, 10, 100, 200, 511 ],
[ 'LONGTEXT', 500, 1, 2, 5, 10, 100, 200, 511 ],
[ 'LONGBLOB', 500, 1, 2, 5, 10, 100, 200, 511 ],
# [ 'VARCHAR(4096)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095 ],
# [ 'VARCHAR(16383)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095, 4096, 16383 ],
# [ 'VARBINARY(16383)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095, 4096, 16383 ],
];
my $table = 'hstesttbl';
my $dbh;
for my $rec (@$string_types) {
my ($typ, $keylen, @vs) = @$rec;
my @vals = ();
for my $len (@vs) {
my $s = '';
my @arr = ();
srand(999);
# print "$len 1\n";
for (my $i = 0; $i < $len; ++$i) {
my $v = int(rand(10));
$arr[$i] = chr(65 + $v);
}
# print "2\n";
push(@vals, join('', @arr));
}
print("TYPE $typ\n");
test_one($typ, $keylen, \@vals);
print("\n");
}
sub test_one {
my ($typ, $keylen, $values) = @_;
my $keylen_str = '';
if (defined($keylen)) {
$keylen_str = "($keylen)";
}
$dbh = hstest::init_testdb();
$dbh->do(
"create table $table (" .
"k $typ, " .
"v1 varchar(2047), " .
"v2 $typ, " .
"primary key(k$keylen_str), " .
"index i1(v1), index i2(v2$keylen_str, v1(300))) " .
"engine = myisam default charset = latin1");
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v1,v2');
$hs->open_index(2, $dbname, $table, 'i1', 'k,v1,v2');
$hs->open_index(3, $dbname, $table, 'i2', 'k,v1,v2');
for my $k (@$values) {
my $kstr = 's' . $k;
$hs->execute_single(1, '+', [ $k, $kstr, $k ], 0, 0);
}
# dump_table();
for my $k (@$values) {
my $kstr = 's' . $k;
my ($rk, $rv1, $rv2);
my $r;
$r = $hs->execute_single(1, '=', [ $k ], 1, 0);
shift(@$r);
check_value("$typ:PK", @$r);
$r = $hs->execute_single(2, '=', [ $kstr ], 1, 0);
shift(@$r);
check_value("$typ:I1", @$r);
$r = $hs->execute_single(3, '=', [ $k, $kstr ], 1, 0);
shift(@$r);
check_value("$typ:I2", @$r);
$r = $hs->execute_single(3, '=', [ $k ], 1, 0);
shift(@$r);
check_value("$typ:I2p", @$r);
}
}
sub check_value {
my ($mess, $rk, $rv1, $rv2) = @_;
$rk ||= '';
$rv1 ||= '';
$rv2 ||= '';
if ($rv2 ne $rk) {
print "$mess: V2 NE\n$rk\n$rv2\n";
return;
}
if ($rv1 ne 's' . $rk) {
print "$mess: V1 NE\n$rk\n$rv1\n";
return;
}
print "$mess: EQ\n";
}
sub dump_table {
print "DUMP_TABLE_BEGIN\n";
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
for my $row (@$aref) {
my ($k, $v1, $v2) = @$row;
$v1 = "[null]" if !defined($v1);
$v2 = "[null]" if !defined($v2);
print "$k $v1 $v2\n";
# print "MISMATCH\n" if ($valmap{$k} ne $v);
}
print "DUMP_TABLE_END\n";
}
HSINSERT
1 v1hs_0
2 v1hs_1
3 v1hs_2
4 v1hs_3
5 v1hs_4
6 v1hs_5
7 v1hs_6
8 v1hs_7
9 v1hs_8
10 v1hs_9
DUMP_TABLE
1 v1hs_0
2 v1hs_1
3 v1hs_2
4 v1hs_3
5 v1hs_4
6 v1hs_5
7 v1hs_6
8 v1hs_7
9 v1hs_8
10 v1hs_9
#!/usr/bin/perl
# vim:sw=2:ai
# tests that columns to be inserted are specified by open_index
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 10;
$dbh->do(
"create table $table (" .
"k int primary key auto_increment, " .
"v1 varchar(30), " .
"v2 varchar(30)) " .
"engine = myisam default charset = binary");
srand(999);
my %valmap = ();
print "HSINSERT\n";
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'v1');
# inserts with auto_increment
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = 0;
my $v1 = "v1hs_" . $i;
my $v2 = "v2hs_" . $i;
my $r = $hs->execute_insert(1, [ $v1 ]);
my $err = $r->[0];
if ($err != 0) {
my $err_str = $r->[1];
print "$err $err_str\n";
} else {
my $id = $r->[1];
print "$id $v1\n";
}
}
undef $hs;
dump_table();
sub dump_table {
print "DUMP_TABLE\n";
my $aref = $dbh->selectall_arrayref("select k,v1,v2 from $table order by k");
for my $row (@$aref) {
my ($k, $v1, $v2) = @$row;
$v1 = "[null]" if !defined($v1);
$v2 = "[null]" if !defined($v2);
print "$k $v1 $v2\n";
# print "MISMATCH\n" if ($valmap{$k} ne $v);
}
}
This diff is collapsed.
#!/usr/bin/perl
# vim:sw=2:ai
# test for filters
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use bigint;
use hstest;
my $numeric_types = [
[ 'TINYINT', -128, 127 ],
[ 'TINYINT UNSIGNED', 0, 255 ],
[ 'SMALLINT', -32768, 32768 ],
[ 'SMALLINT UNSIGNED', 0, 65535 ],
[ 'MEDIUMINT', -8388608, 8388607 ],
[ 'MEDIUMINT UNSIGNED', 0, 16777215 ],
[ 'INT', -2147483648, 2147483647 ],
[ 'INT UNSIGNED', 0, 4294967295 ],
[ 'BIGINT', -9223372036854775808, 9223372036854775807 ],
[ 'BIGINT UNSIGNED', 0, 18446744073709551615 ],
[ 'FLOAT', -32768, 32768 ],
[ 'DOUBLE', -2147483648, 2147483647 ],
];
my $datetime_types = [
[ 'DATE', '0000-00-00', '2011-01-01', '9999-12-31' ],
[ 'DATETIME', 0, '2011-01-01 18:30:25' ],
[ 'TIME', 0, '18:30:25' ],
[ 'YEAR(4)', 1901, 2011, 2155 ],
# [ 'TIMESTAMP', 0, 999999999 ], # DOES NOT WORK YET
];
my $string_types = [
[ 'CHAR(10)', undef, 1, 2, 5, 10 ],
[ 'VARCHAR(10)', undef, 1, 2, 5, 10 ],
[ 'BINARY(10)', undef, 1, 2, 5, 10 ],
[ 'VARBINARY(10)', undef, 1, 2, 5, 10 ],
[ 'CHAR(255)', undef, 1, 2, 5, 10, 100, 200, 255 ],
[ 'VARCHAR(255)', undef, 1, 2, 5, 10, 100, 200, 255 ],
[ 'VARCHAR(511)', undef, 1, 2, 5, 10, 100, 200, 511 ],
[ 'LONGTEXT', 500, 1, 2, 5, 10, 100, 200, 511 ], # NOT SUPPORTED YET
[ 'LONGBLOB', 500, 1, 2, 5, 10, 100, 200, 511 ], # NOT SUPPORTED YET
# [ 'VARCHAR(4096)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095 ],
# [ 'VARCHAR(16383)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095, 4096, 16383 ],
# [ 'VARBINARY(16383)', 500, 1, 2, 5, 10, 100, 200, 255, 256, 4095, 4096, 16383 ],
];
for my $rec (@$numeric_types) {
my ($typ, $minval, $maxval) = @$rec;
my @vals = ();
push(@vals, 0);
push(@vals, $maxval);
if ($minval != 0) {
push(@vals, $minval);
}
my $v1 = $minval;
my $v2 = $maxval;
for (my $i = 0; $i < 3; ++$i) {
$v1 /= 3;
$v2 /= 3;
push(@vals, int($v1));
push(@vals, int($v2));
}
my %vm = map { $_ => 1 } @vals;
@vals = sort { $a <=> $b } keys %vm;
push(@vals, undef);
test_one($typ, undef, \@vals);
}
for my $rec (@$datetime_types) {
my ($typ, @vals) = @$rec;
push(@vals, undef);
test_one($typ, undef, \@vals);
}
for my $rec (@$string_types) {
my ($typ, $keylen, @vs) = @$rec;
my @vals = ();
srand(999);
for my $len (@vs) {
my $s = '';
my @arr = ();
# print "$len 1\n";
for (my $i = 0; $i < $len; ++$i) {
my $v = int(rand(10));
$arr[$i] = chr(65 + $v);
}
# print "2\n";
push(@vals, join('', @arr));
}
push(@vals, undef);
test_one($typ, $keylen, \@vals);
}
my $hs;
sub test_one {
my ($typ, $keylen, $values) = @_;
print "\n$typ -------------------------------------------------\n\n";
my $keylen_str = '';
if (defined($keylen)) {
$keylen_str = "($keylen)";
}
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 3;
$dbh->do(
"create table $table " .
"(k1 int not null, k2 int not null, " .
"v1 int not null, v2 $typ default null, " .
"primary key (k1, k2) ) engine = innodb");
my $sth = $dbh->prepare("insert into $table values (?,?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $j = 0;
for my $v (@$values) {
$sth->execute($i, $j, $i, $v);
++$j;
}
}
$hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k1,k2,v1,v2', 'v2');
my $minval = $values->[0];
# select * ... where (k1, k2) >= ('', $minval)
exec_multi(
4, "FILTER($typ) NO FILTER",
[ 1, '>=', [ '', $minval ], 1000, 0 ]
);
for my $v (@$values) {
my $vstr = defined($v) ? $v : 'NULL';
# select * ... where (k1, k2) >= ('', $minval) and v2 = $v
exec_multi(
4, "FILTER($typ) v2 = $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '=', 0, $v ] ] ]
);
# select * ... where (k1, k2) >= ('', $minval) and v2 != $v
exec_multi(
4, "FILTER($typ) v2 != $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '!=', 0, $v ] ] ]
);
# select * ... where (k1, k2) >= ('', $minval) and v2 >= $v
exec_multi(
4, "FILTER($typ) v2 >= $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '>=', 0, $v ] ] ]
);
# select * ... where (k1, k2) >= ('', $minval) and v2 < $v
exec_multi(
4, "FILTER($typ) v2 < $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '<', 0, $v ] ] ]
);
# select * ... where (k1, k2) >= ('', $minval) and v2 > $v
exec_multi(
4, "FILTER($typ) v2 > $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '>', 0, $v ] ] ]
);
# select * ... where (k1, k2) >= ('', $minval) and v2 <= $v
exec_multi(
4, "FILTER($typ) v2 <= $vstr",
[ 1, '>=', [ '', $minval ], 1000, 0, undef, undef, [ [ 'F', '<=', 0, $v ] ] ]
);
}
undef $hs;
}
sub exec_multi {
my $width = shift(@_);
my $mess = shift(@_);
print "$mess\n";
my $mres = $hs->execute_multi(\@_);
for my $res (@$mres) {
my $code = shift(@$res);
my $nrows = $code == 0 ? scalar(@$res) / $width : 0;
print "code=$code rows=$nrows\n";
my $i = 0;
for my $fld (@$res) {
$fld = 'NULL' if !defined($fld);
print "[$fld]";
if (++$i >= $width) {
print "\n";
$i = 0;
}
}
print "\n";
}
}
#!/usr/bin/perl
# vim:sw=2:ai
# test for a bug that table mdl is not released when open_index is failed
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $dbname = $hstest::conf{dbname};
my $table = 'hstesttbl';
$dbh->do("drop table if exists $table");
my $hs = hstest::get_hs_connection();
my $r = $hs->open_index(1, $dbname, $table, '', 'k,v'); # fails
print "open_index 1st r=$r\n";
undef $hs;
$dbh->do(
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
"engine = innodb");
$hs = hstest::get_hs_connection();
$r = $hs->open_index(1, $dbname, $table, '', 'k,v'); # success
print "open_index 2nd r=$r\n";
HS
k10 v704-10
k30 v52-30
k40 v878-40
k50 v682-50
SQL
k10 v704-10
k30 v52-30
k40 v878-40
k50 v682-50
END
#!/usr/bin/perl
# vim:sw=2:ai
# test for 'IN'
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 100;
$dbh->do(
"create table $table (k varchar(30) primary key, v varchar(30) not null) " .
"engine = innodb");
srand(999);
my %valmap = ();
my $sth = $dbh->prepare("insert into $table values (?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = "k" . $i;
my $v = "v" . int(rand(1000)) . "-" . $i;
$sth->execute($k, $v);
$valmap{$k} = $v;
}
my $hs = hstest::get_hs_connection();
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v');
my $vs = [ 'k10', 'k20x', 'k30', 'k40', 'k50' ];
# select k,v from $table where k in $vs
my $r = $hs->execute_single(1, '=', [ '' ], 10000, 0, undef, undef, undef,
0, $vs);
shift(@$r);
print "HS\n";
my $len = scalar(@$r) / 2;
for (my $i = 0; $i < $len; ++$i) {
my $k = $r->[$i * 2];
my $v = $r->[$i * 2 + 1];
print "$k $v\n";
}
print "SQL\n";
my $aref = $dbh->selectall_arrayref(
"select k,v from $table where k in ('k10', 'k20x', 'k30', 'k40', 'k50') "
. "order by k");
for my $row (@$aref) {
my ($k, $v) = @$row;
print "$k $v\n";
}
print "END\n";
HS
k10 v704-10 1
k30 v52-30 1
k50 v682-50 1
SQL
k10 v704-10 1
k30 v52-30 1
k50 v682-50 1
END
#!/usr/bin/perl
# vim:sw=2:ai
# test for 'IN' and filters
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 100;
$dbh->do(
"create table $table (k varchar(30) primary key, " .
"v varchar(30) not null, v2 int not null) " .
"engine = innodb");
srand(999);
my %valmap = ();
my $sth = $dbh->prepare("insert into $table values (?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = "k" . $i;
my $v = "v" . int(rand(1000)) . "-" . $i;
my $v2 = ($i / 10) % 2;
$sth->execute($k, $v, $v2);
$valmap{$k} = $v;
}
my $hs = hstest::get_hs_connection();
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v,v2', 'v2');
my $vs = [ 'k10', 'k20x', 'k30', 'k40', 'k50' ];
# select k,v,v2 from $table where k in $vs
my $r = $hs->execute_single(1, '=', [ '' ], 10000, 0, undef, undef,
[['F', '=', 0, '1']], 0, $vs);
shift(@$r);
print "HS\n";
my $len = scalar(@$r) / 3;
for (my $i = 0; $i < $len; ++$i) {
my $k = $r->[$i * 3];
my $v = $r->[$i * 3 + 1];
my $v2 = $r->[$i * 3 + 2];
print "$k $v $v2\n";
}
print "SQL\n";
my $aref = $dbh->selectall_arrayref(
"select k,v,v2 from $table where k in ('k10', 'k20x', 'k30', 'k40', 'k50') "
. "and v2 = '1' order by k");
for my $row (@$aref) {
my ($k, $v, $v2) = @$row;
print "$k $v $v2\n";
}
print "END\n";
HS
k0 v102-0 0
k1 v635-1 0
k10 MOD 1
k11 v751-11 1
k12 v367-12 1
k13 v400-13 1
k14 v397-14 1
k15 v170-15 1
k16 v719-16 1
k17 v734-17 1
k18 v587-18 1
k19 v494-19 1
k2 v803-2 0
k20 v523-20 0
k21 v954-21 0
k22 v433-22 0
k23 v820-23 0
k24 v283-24 0
k25 v837-25 0
k26 v205-26 0
k27 v415-27 0
k28 v545-28 0
k29 v583-29 0
k3 v925-3 0
k30 MOD 1
k31 v323-31 1
k32 v614-32 1
k33 v679-33 1
k34 v805-34 1
k35 v451-35 1
k36 v115-36 1
k37 v269-37 1
k38 v218-38 1
k39 v617-39 1
k4 v775-4 0
k40 v878-40 0
k41 v345-41 0
k42 v512-42 0
k43 v969-43 0
k44 v408-44 0
k45 v291-45 0
k46 v858-46 0
k47 v953-47 0
k48 v710-48 0
k49 v142-49 0
k5 v537-5 0
k50 MOD 1
k51 v934-51 1
k52 v621-52 1
k53 v965-53 1
k54 v574-54 1
k55 v204-55 1
k56 v298-56 1
k57 v134-57 1
k58 v983-58 1
k59 v444-59 1
k6 v592-6 0
k60 v144-60 0
k61 v152-61 0
k62 v187-62 0
k63 v215-63 0
k64 v8-64 0
k65 v697-65 0
k66 v651-66 0
k67 v280-67 0
k68 v701-68 0
k69 v537-69 0
k7 v414-7 0
k70 v413-70 1
k71 v69-71 1
k72 v86-72 1
k73 v822-73 1
k74 v670-74 1
k75 v370-75 1
k76 v806-76 1
k77 v688-77 1
k78 v26-78 1
k79 v66-79 1
k8 v590-8 0
k80 v802-80 0
k81 v171-81 0
k82 v557-82 0
k83 v847-83 0
k84 v777-84 0
k85 v730-85 0
k86 v987-86 0
k87 v115-87 0
k88 v646-88 0
k89 v496-89 0
k9 v302-9 0
k90 v120-90 1
k91 v684-91 1
k92 v374-92 1
k93 v65-93 1
k94 v370-94 1
k95 v174-95 1
k96 v828-96 1
k97 v867-97 1
k98 v759-98 1
k99 v703-99 1
#!/usr/bin/perl
# vim:sw=2:ai
# test for 'IN', filters, and modifications
BEGIN {
push @INC, "../common/";
};
use strict;
use warnings;
use hstest;
my $dbh = hstest::init_testdb();
my $table = 'hstesttbl';
my $tablesize = 100;
$dbh->do(
"create table $table (k varchar(30) primary key, " .
"v varchar(30) not null, v2 int not null) " .
"engine = innodb");
srand(999);
my %valmap = ();
my $sth = $dbh->prepare("insert into $table values (?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = "k" . $i;
my $v = "v" . int(rand(1000)) . "-" . $i;
my $v2 = ($i / 10) % 2;
$sth->execute($k, $v, $v2);
$valmap{$k} = $v;
}
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(1, $dbname, $table, '', 'k,v,v2', 'v2');
$hs->open_index(2, $dbname, $table, '', 'v', 'v2');
my $vs = [ 'k10', 'k20x', 'k30', 'k40', 'k50' ];
# update $table set v = 'MOD' where k in $vs and v2 = '1'
my $r = $hs->execute_single(2, '=', [ '' ], 10000, 0, 'U', [ 'MOD' ],
[['F', '=', 0, '1']], 0, $vs);
$r = $hs->execute_single(1, '>=', [ '' ], 10000, 0);
shift(@$r);
print "HS\n";
my $len = scalar(@$r) / 3;
for (my $i = 0; $i < $len; ++$i) {
my $k = $r->[$i * 3];
my $v = $r->[$i * 3 + 1];
my $v2 = $r->[$i * 3 + 2];
print "$k $v $v2\n";
}
......@@ -2687,6 +2687,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
void handler::ha_release_auto_increment()
{
DBUG_ENTER("ha_release_auto_increment");
release_auto_increment();
insert_id_for_cur_row= 0;
auto_inc_interval_for_cur_row.replace(0, 0, 0);
......@@ -2700,6 +2701,7 @@ void handler::ha_release_auto_increment()
*/
table->in_use->auto_inc_intervals_forced.empty();
}
DBUG_VOID_RETURN;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment