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 \ ...@@ -84,7 +84,6 @@ TEST_DIRS = t r include std_data std_data/parts collections \
std_data/funcs_1 \ std_data/funcs_1 \
extra/binlog_tests/ extra/rpl_tests \ extra/binlog_tests/ extra/rpl_tests \
suite/binlog suite/binlog/t suite/binlog/r suite/binlog/std_data \ 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/federated \
suite/pbxt/t suite/pbxt/r suite/pbxt \ suite/pbxt/t suite/pbxt/r suite/pbxt \
suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \ suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \
......
...@@ -17,3 +17,6 @@ Moriyoshi Koizumi (https://github.com/moriyoshi) ...@@ -17,3 +17,6 @@ Moriyoshi Koizumi (https://github.com/moriyoshi)
takeda-at (https://github.com/takada-at) takeda-at (https://github.com/takada-at)
- added simple authorization function - added simple authorization function
WheresWardy (https://github.com/WheresWardy)
- added authentication functions to libhsclient
...@@ -6,9 +6,19 @@ hsclient_LDFLAGS= -static -L../libhsclient -lhsclient ...@@ -6,9 +6,19 @@ hsclient_LDFLAGS= -static -L../libhsclient -lhsclient
hsclient_CXXFLAGS= $(AM_INCLUDES) hsclient_CXXFLAGS= $(AM_INCLUDES)
hstest: hstest.o hstest: hstest.o
$(CXX) $(CXXFLAGS) $(LFLAGS) hstest.o \ $(CXX) $(CXXFLAGS) $(MY_CXXFLAGS) $(LFLAGS) hstest.o \
-L../libhsclient/.libs -lhsclient $(MYSQL_LIB) -o hstest -L../libhsclient/.libs -lhsclient $(MYSQL_LIB) \
-o hstest
hstest.o: hstest.cpp 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
// vim:sw=2:ai
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>
#include <stdlib.h>
#include <memory>
#include <errno.h>
#include <mysql.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "util.hpp"
#include "auto_ptrcontainer.hpp"
#include "socket.hpp"
#include "hstcpcli.hpp"
#include "string_util.hpp"
#include "mutex.hpp"
namespace dena {
struct auto_mysql : private noncopyable {
auto_mysql() : db(0) {
reset();
}
~auto_mysql() {
if (db) {
mysql_close(db);
}
}
void reset() {
if (db) {
mysql_close(db);
}
if ((db = mysql_init(0)) == 0) {
fatal_exit("failed to initialize mysql client");
}
}
operator MYSQL *() const { return db; }
private:
MYSQL *db;
};
struct auto_mysql_res : private noncopyable {
auto_mysql_res(MYSQL *db) {
res = mysql_store_result(db);
}
~auto_mysql_res() {
if (res) {
mysql_free_result(res);
}
}
operator MYSQL_RES *() const { return res; }
private:
MYSQL_RES *res;
};
struct auto_mysql_stmt : private noncopyable {
auto_mysql_stmt(MYSQL *db) {
stmt = mysql_stmt_init(db);
}
~auto_mysql_stmt() {
if (stmt) {
mysql_stmt_close(stmt);
}
}
operator MYSQL_STMT *() const { return stmt; }
private:
MYSQL_STMT *stmt;
};
double
gettimeofday_double()
{
struct timeval tv = { };
if (gettimeofday(&tv, 0) != 0) {
fatal_abort("gettimeofday");
}
return static_cast<double>(tv.tv_usec) / 1000000 + tv.tv_sec;
}
struct record_value {
mutex lock;
bool deleted;
bool unknown_state;
std::string key;
std::vector<std::string> values;
record_value() : deleted(true), unknown_state(false) { }
};
struct hs_longrun_shared {
config conf;
socket_args arg;
int verbose;
long num_threads;
int usleep;
volatile mutable int running;
auto_ptrcontainer< std::vector<record_value *> > records;
hs_longrun_shared() : verbose(0), num_threads(0), usleep(0), running(1) { }
};
struct thread_base {
thread_base() : need_join(false), stack_size(256 * 1024) { }
virtual ~thread_base() {
join();
}
virtual void run() = 0;
void start() {
if (!start_nothrow()) {
fatal_abort("thread::start");
}
}
bool start_nothrow() {
if (need_join) {
return need_join; /* true */
}
void *const arg = this;
pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0) {
fatal_abort("pthread_attr_init");
}
if (pthread_attr_setstacksize(&attr, stack_size) != 0) {
fatal_abort("pthread_attr_setstacksize");
}
const int r = pthread_create(&thr, &attr, thread_main, arg);
if (pthread_attr_destroy(&attr) != 0) {
fatal_abort("pthread_attr_destroy");
}
if (r != 0) {
return need_join; /* false */
}
need_join = true;
return need_join; /* true */
}
void join() {
if (!need_join) {
return;
}
int e = 0;
if ((e = pthread_join(thr, 0)) != 0) {
fatal_abort("pthread_join");
}
need_join = false;
}
private:
static void *thread_main(void *arg) {
thread_base *p = static_cast<thread_base *>(arg);
p->run();
return 0;
}
private:
pthread_t thr;
bool need_join;
size_t stack_size;
};
struct hs_longrun_stat {
unsigned long long verify_error_count;
unsigned long long runtime_error_count;
unsigned long long unknown_count;
unsigned long long success_count;
hs_longrun_stat()
: verify_error_count(0), runtime_error_count(0),
unknown_count(0), success_count(0) { }
void add(const hs_longrun_stat& x) {
verify_error_count += x.verify_error_count;
runtime_error_count += x.runtime_error_count;
unknown_count += x.unknown_count;
success_count += x.success_count;
}
};
struct hs_longrun_thread_base : public thread_base {
struct arg_type {
int id;
std::string worker_type;
char op;
int lock_flag;
const hs_longrun_shared& sh;
arg_type(int id, const std::string& worker_type, char op, int lock_flag,
const hs_longrun_shared& sh)
: id(id), worker_type(worker_type), op(op), lock_flag(lock_flag),
sh(sh) { }
};
arg_type arg;
hs_longrun_stat stat;
drand48_data randbuf;
unsigned int seed;
hs_longrun_thread_base(const arg_type& arg)
: arg(arg), seed(0) {
seed = time(0) + arg.id + 1;
srand48_r(seed, &randbuf);
}
virtual ~hs_longrun_thread_base() { }
virtual void run() = 0;
size_t rand_record() {
double v = 0;
drand48_r(&randbuf, &v);
const size_t sz = arg.sh.records.size();
size_t r = size_t(v * sz);
if (r >= sz) {
r = 0;
}
return r;
}
int verify_update(const std::string& k, const std::string& v1,
const std::string& v2, const std::string& v3, record_value& rec,
uint32_t num_rows, bool cur_unknown_state);
int verify_read(const std::string& k, uint32_t num_rows, uint32_t num_flds,
const std::string rrec[4], record_value& rec);
int verify_readnolock(const std::string& k, uint32_t num_rows,
uint32_t num_flds, const std::string rrec[4]);
};
int
hs_longrun_thread_base::verify_update(const std::string& k,
const std::string& v1, const std::string& v2, const std::string& v3,
record_value& rec, uint32_t num_rows, bool cur_unknown_state)
{
const bool op_success = num_rows == 1;
int ret = 0;
if (!rec.unknown_state) {
if (!rec.deleted && !op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_update_failure\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
} else if (rec.deleted && op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_update_success\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
}
}
if (op_success) {
rec.values.resize(4);
rec.values[0] = k;
rec.values[1] = v1;
rec.values[2] = v2;
rec.values[3] = v3;
if (ret == 0 && !rec.unknown_state) {
++stat.success_count;
}
}
rec.unknown_state = cur_unknown_state;
if (arg.sh.verbose >= 100 && ret == 0) {
fprintf(stderr, "%s %s %s %s %s\n", arg.worker_type.c_str(),
k.c_str(), v1.c_str(), v2.c_str(), v3.c_str());
}
return ret;
}
int
hs_longrun_thread_base::verify_read(const std::string& k,
uint32_t num_rows, uint32_t num_flds, const std::string rrec[4],
record_value& rec)
{
const bool op_success = num_rows != 0;
int ret = 0;
if (!rec.unknown_state) {
if (!rec.deleted && !op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_read_failure\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
} else if (rec.deleted && op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_read_success\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
} else if (num_flds != 4) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_read_fldnum %d\n",
arg.worker_type.c_str(), arg.id, k.c_str(),
static_cast<int>(num_flds));
}
ret = 1;
} else if (rec.deleted) {
/* nothing to verify */
} else {
int diff = 0;
for (size_t i = 0; i < 4; ++i) {
if (rec.values[i] == rrec[i]) {
/* ok */
} else {
diff = 1;
}
}
if (diff) {
std::string mess;
for (size_t i = 0; i < 4; ++i) {
const std::string& expected = rec.values[i];
const std::string& val = rrec[i];
mess += " " + val + "/" + expected;
}
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_read_value %s\n",
arg.worker_type.c_str(), arg.id, k.c_str(), mess.c_str());
}
ret = 1;
}
}
}
if (arg.sh.verbose >= 100 && ret == 0) {
fprintf(stderr, "%s %s\n", arg.worker_type.c_str(), k.c_str());
}
if (ret == 0 && !rec.unknown_state) {
++stat.success_count;
}
return ret;
}
int
hs_longrun_thread_base::verify_readnolock(const std::string& k,
uint32_t num_rows, uint32_t num_flds, const std::string rrec[4])
{
int ret = 0;
if (num_rows != 1 || num_flds != 4) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_read_failure\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
}
if (arg.sh.verbose >= 100 && ret == 0) {
fprintf(stderr, "%s -> %s %s %s %s %s\n", arg.worker_type.c_str(),
k.c_str(), rrec[0].c_str(), rrec[1].c_str(), rrec[2].c_str(),
rrec[3].c_str());
}
if (ret == 0) {
++stat.success_count;
}
return ret;
}
struct hs_longrun_thread_hs : public hs_longrun_thread_base {
hs_longrun_thread_hs(const arg_type& arg)
: hs_longrun_thread_base(arg) { }
void run();
int check_hs_error(const char *mess, record_value *rec);
int op_insert(record_value& rec);
int op_delete(record_value& rec);
int op_update(record_value& rec);
int op_read(record_value& rec);
int op_readnolock(int k);
hstcpcli_ptr cli;
socket_args sockargs;
};
struct lock_guard : noncopyable {
lock_guard(mutex& mtx) : mtx(mtx) {
mtx.lock();
}
~lock_guard() {
mtx.unlock();
}
mutex& mtx;
};
string_ref
to_string_ref(const std::string& s)
{
return string_ref(s.data(), s.size());
}
std::string
to_string(const string_ref& s)
{
return std::string(s.begin(), s.size());
}
void
hs_longrun_thread_hs::run()
{
config c = arg.sh.conf;
if (arg.op == 'R' || arg.op == 'N') {
c["port"] = to_stdstring(arg.sh.conf.get_int("hsport", 9998));
} else {
c["port"] = to_stdstring(arg.sh.conf.get_int("hsport_wr", 9999));
}
sockargs.set(c);
while (arg.sh.running) {
if (cli.get() == 0 || !cli->stable_point()) {
cli = hstcpcli_i::create(sockargs);
if (check_hs_error("connect", 0) != 0) {
cli.reset();
continue;
}
cli->request_buf_open_index(0, "hstestdb", "hstesttbl", "PRIMARY",
"k,v1,v2,v3", "k,v1,v2,v3");
cli->request_send();
if (check_hs_error("openindex_send", 0) != 0) {
cli.reset();
continue;
}
size_t num_flds = 0;
cli->response_recv(num_flds);
if (check_hs_error("openindex_recv", 0) != 0) {
cli.reset();
continue;
}
cli->response_buf_remove();
}
const size_t rec_id = rand_record();
if (arg.lock_flag) {
record_value& rec = *arg.sh.records[rec_id];
lock_guard g(rec.lock);
int e = 0;
switch (arg.op) {
case 'I':
e = op_insert(rec);
break;
case 'D':
e = op_delete(rec);
break;
case 'U':
e = op_update(rec);
break;
case 'R':
e = op_read(rec);
break;
default:
break;
}
} else {
int e = 0;
switch (arg.op) {
case 'N':
e = op_readnolock(rec_id);
break;
default:
break;
}
}
}
}
int
hs_longrun_thread_hs::op_insert(record_value& rec)
{
const std::string k = rec.key;
const std::string v1 = "iv1_" + k + "_" + to_stdstring(arg.id);
const std::string v2 = "iv2_" + k + "_" + to_stdstring(arg.id);
const std::string v3 = "iv3_" + k + "_" + to_stdstring(arg.id);
const string_ref op_ref("+", 1);
const string_ref op_args[4] = {
to_string_ref(k),
to_string_ref(v1),
to_string_ref(v2),
to_string_ref(v3)
};
cli->request_buf_exec_generic(0, op_ref, op_args, 4, 1, 0,
string_ref(), 0, 0, 0, 0);
cli->request_send();
if (check_hs_error("op_insert_send", &rec) != 0) { return 1; }
size_t numflds = 0;
cli->response_recv(numflds);
if (arg.sh.verbose > 10) {
const string_ref *row = cli->get_next_row();
fprintf(stderr, "HS op=+ errrcode=%d errmess=[%s]\n", cli->get_error_code(),
row ? to_string(row[0]).c_str() : "");
}
const bool op_success = cli->get_error_code() == 0;
int ret = 0;
if (!rec.unknown_state) {
if (rec.deleted && !op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_insert_failure\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
} else if (!rec.deleted && op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_insert_success\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
}
} else {
++stat.unknown_count;
}
if (op_success) {
rec.values.resize(4);
rec.values[0] = k;
rec.values[1] = v1;
rec.values[2] = v2;
rec.values[3] = v3;
rec.deleted = false;
if (arg.sh.verbose >= 100 && ret == 0) {
fprintf(stderr, "HS_INSERT %s %s %s %s\n", k.c_str(), v1.c_str(),
v2.c_str(), v3.c_str());
}
if (ret == 0 && !rec.unknown_state) {
++stat.success_count;
}
rec.unknown_state = false;
}
cli->response_buf_remove();
return ret;
}
int
hs_longrun_thread_hs::op_delete(record_value& rec)
{
const std::string k = rec.key;
const string_ref op_ref("=", 1);
const string_ref op_args[1] = {
to_string_ref(k),
};
const string_ref modop_ref("D", 1);
cli->request_buf_exec_generic(0, op_ref, op_args, 1, 1, 0,
modop_ref, 0, 0, 0, 0);
cli->request_send();
if (check_hs_error("op_delete_send", &rec) != 0) { return 1; }
size_t numflds = 0;
cli->response_recv(numflds);
if (check_hs_error("op_delete_recv", &rec) != 0) { return 1; }
const string_ref *row = cli->get_next_row();
const bool op_success = (numflds > 0 && row != 0 &&
to_string(row[0]) == "1");
int ret = 0;
if (!rec.unknown_state) {
if (!rec.deleted && !op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_delete_failure\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
} else if (rec.deleted && op_success) {
++stat.verify_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "VERIFY_ERROR: %s wid=%d k=%s "
"unexpected_delete_success\n",
arg.worker_type.c_str(), arg.id, k.c_str());
}
ret = 1;
}
}
cli->response_buf_remove();
if (op_success) {
rec.deleted = true;
if (ret == 0 && !rec.unknown_state) {
++stat.success_count;
}
rec.unknown_state = false;
}
if (arg.sh.verbose >= 100 && ret == 0) {
fprintf(stderr, "HS_DELETE %s\n", k.c_str());
}
return ret;
}
int
hs_longrun_thread_hs::op_update(record_value& rec)
{
const std::string k = rec.key;
const std::string v1 = "uv1_" + k + "_" + to_stdstring(arg.id);
const std::string v2 = "uv2_" + k + "_" + to_stdstring(arg.id);
const std::string v3 = "uv3_" + k + "_" + to_stdstring(arg.id);
const string_ref op_ref("=", 1);
const string_ref op_args[1] = {
to_string_ref(k),
};
const string_ref modop_ref("U", 1);
const string_ref modop_args[4] = {
to_string_ref(k),
to_string_ref(v1),
to_string_ref(v2),
to_string_ref(v3)
};
cli->request_buf_exec_generic(0, op_ref, op_args, 1, 1, 0,
modop_ref, modop_args, 4, 0, 0);
cli->request_send();
if (check_hs_error("op_update_send", &rec) != 0) { return 1; }
size_t numflds = 0;
cli->response_recv(numflds);
if (check_hs_error("op_update_recv", &rec) != 0) { return 1; }
const string_ref *row = cli->get_next_row();
uint32_t num_rows = row
? atoi_uint32_nocheck(row[0].begin(), row[0].end()) : 0;
cli->response_buf_remove();
const bool cur_unknown_state = (num_rows == 1);
return verify_update(k, v1, v2, v3, rec, num_rows, cur_unknown_state);
}
int
hs_longrun_thread_hs::op_read(record_value& rec)
{
const std::string k = rec.key;
const string_ref op_ref("=", 1);
const string_ref op_args[1] = {
to_string_ref(k),
};
cli->request_buf_exec_generic(0, op_ref, op_args, 1, 1, 0,
string_ref(), 0, 0, 0, 0);
cli->request_send();
if (check_hs_error("op_read_send", 0) != 0) { return 1; }
size_t num_flds = 0;
size_t num_rows = 0;
cli->response_recv(num_flds);
if (check_hs_error("op_read_recv", 0) != 0) { return 1; }
const string_ref *row = cli->get_next_row();
std::string rrec[4];
if (row != 0 && num_flds == 4) {
for (int i = 0; i < 4; ++i) {
rrec[i] = to_string(row[i]);
}
++num_rows;
}
row = cli->get_next_row();
if (row != 0) {
++num_rows;
}
cli->response_buf_remove();
return verify_read(k, num_rows, num_flds, rrec, rec);
}
int
hs_longrun_thread_hs::op_readnolock(int key)
{
const std::string k = to_stdstring(key);
const string_ref op_ref("=", 1);
const string_ref op_args[1] = {
to_string_ref(k),
};
cli->request_buf_exec_generic(0, op_ref, op_args, 1, 1, 0,
string_ref(), 0, 0, 0, 0);
cli->request_send();
if (check_hs_error("op_read_send", 0) != 0) { return 1; }
size_t num_flds = 0;
size_t num_rows = 0;
cli->response_recv(num_flds);
if (check_hs_error("op_read_recv", 0) != 0) { return 1; }
const string_ref *row = cli->get_next_row();
std::string rrec[4];
if (row != 0 && num_flds == 4) {
for (int i = 0; i < 4; ++i) {
rrec[i] = to_string(row[i]);
}
++num_rows;
}
row = cli->get_next_row();
if (row != 0) {
++num_rows;
}
cli->response_buf_remove();
return verify_readnolock(k, num_rows, num_flds, rrec);
}
int
hs_longrun_thread_hs::check_hs_error(const char *mess, record_value *rec)
{
const int err = cli->get_error_code();
if (err == 0) {
return 0;
}
++stat.runtime_error_count;
if (arg.sh.verbose > 0) {
const std::string estr = cli->get_error();
fprintf(stderr, "RUNTIME_ERROR: op=%c wid=%d %s: %d %s\n",
arg.op, arg.id, mess, err, estr.c_str());
}
if (rec) {
rec->unknown_state = true;
}
return 1;
}
struct hs_longrun_thread_my : public hs_longrun_thread_base {
hs_longrun_thread_my(const arg_type& arg)
: hs_longrun_thread_base(arg), connected(false) { }
void run();
void show_mysql_error(const char *mess, record_value *rec);
int op_insert(record_value& rec);
int op_delete(record_value& rec);
int op_update(record_value& rec);
int op_delins(record_value& rec);
int op_read(record_value& rec);
auto_mysql db;
bool connected;
};
void
hs_longrun_thread_my::run()
{
const std::string mysql_host = arg.sh.conf.get_str("host", "localhost");
const std::string mysql_user = arg.sh.conf.get_str("mysqluser", "root");
const std::string mysql_passwd = arg.sh.conf.get_str("mysqlpass", "");
const std::string mysql_dbname = "hstestdb";
while (arg.sh.running) {
if (!connected) {
if (!mysql_real_connect(db, mysql_host.c_str(), mysql_user.c_str(),
mysql_passwd.c_str(), mysql_dbname.c_str(), mysql_port, 0, 0)) {
show_mysql_error("mysql_real_connect", 0);
continue;
}
}
connected = true;
const size_t rec_id = rand_record();
record_value& rec = *arg.sh.records[rec_id];
lock_guard g(rec.lock);
int e = 0;
switch (arg.op) {
#if 0
case 'I':
e = op_insert(rec);
break;
case 'D':
e = op_delete(rec);
break;
case 'U':
e = op_update(rec);
break;
#endif
case 'T':
e = op_delins(rec);
break;
case 'R':
e = op_read(rec);
break;
default:
break;
}
}
}
int
hs_longrun_thread_my::op_delins(record_value& rec)
{
const std::string k = rec.key;
const std::string v1 = "div1_" + k + "_" + to_stdstring(arg.id);
const std::string v2 = "div2_" + k + "_" + to_stdstring(arg.id);
const std::string v3 = "div3_" + k + "_" + to_stdstring(arg.id);
int success = 0;
bool cur_unknown_state = false;
do {
char query[1024];
#if 1
if (mysql_query(db, "begin") != 0) {
if (arg.sh.verbose >= 20) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), "begin");
}
break;
}
#endif
cur_unknown_state = true;
snprintf(query, 1024,
"delete from hstesttbl where k = '%s'", k.c_str());
if (mysql_query(db, query) != 0) {
if (arg.sh.verbose >= 20) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), query);
}
break;
}
if (mysql_affected_rows(db) != 1) {
if (arg.sh.verbose >= 20) {
fprintf(stderr, "mysql: notfound: [%s]\n", query);
}
break;
}
snprintf(query, 1024,
"insert into hstesttbl values ('%s', '%s', '%s', '%s')",
k.c_str(), v1.c_str(), v2.c_str(), v3.c_str());
if (mysql_query(db, query) != 0) {
if (arg.sh.verbose >= 20) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), query);
}
break;
}
#if 1
if (mysql_query(db, "commit") != 0) {
if (arg.sh.verbose >= 20) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), "commit");
}
break;
}
#endif
success = true;
cur_unknown_state = false;
} while (false);
return verify_update(k, v1, v2, v3, rec, (success != 0), cur_unknown_state);
}
int
hs_longrun_thread_my::op_read(record_value& rec)
{
const std::string k = rec.key;
char query[1024] = { 0 };
const int len = snprintf(query, 1024,
"select k,v1,v2,v3 from hstesttbl where k='%s'", k.c_str());
const int r = mysql_real_query(db, query, len > 0 ? len : 0);
if (r != 0) {
show_mysql_error(query, 0);
return 1;
}
MYSQL_ROW row = 0;
unsigned long *lengths = 0;
unsigned int num_rows = 0;
unsigned int num_flds = 0;
auto_mysql_res res(db);
std::string rrec[4];
if (res != 0) {
num_flds = mysql_num_fields(res);
row = mysql_fetch_row(res);
if (row != 0) {
lengths = mysql_fetch_lengths(res);
if (num_flds == 4) {
for (int i = 0; i < 4; ++i) {
rrec[i] = std::string(row[i], lengths[i]);
}
}
++num_rows;
row = mysql_fetch_row(res);
if (row != 0) {
++num_rows;
}
}
}
return verify_read(k, num_rows, num_flds, rrec, rec);
}
void
hs_longrun_thread_my::show_mysql_error(const char *mess, record_value *rec)
{
++stat.runtime_error_count;
if (arg.sh.verbose > 0) {
fprintf(stderr, "RUNTIME_ERROR: op=%c wid=%d [%s]: %s\n",
arg.op, arg.id, mess, mysql_error(db));
}
if (rec) {
rec->unknown_state = true;
}
db.reset();
connected = false;
}
void
mysql_do(MYSQL *db, const char *query)
{
if (mysql_real_query(db, query, strlen(query)) != 0) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), query);
fatal_exit("mysql_do");
}
}
void
hs_longrun_init_table(const config& conf, int num_prepare,
hs_longrun_shared& shared)
{
const std::string mysql_host = conf.get_str("host", "localhost");
const std::string mysql_user = conf.get_str("mysqluser", "root");
const std::string mysql_passwd = conf.get_str("mysqlpass", "");
const std::string mysql_dbname = "";
auto_mysql db;
if (!mysql_real_connect(db, mysql_host.c_str(), mysql_user.c_str(),
mysql_passwd.c_str(), mysql_dbname.c_str(), mysql_port, 0, 0)) {
fprintf(stderr, "mysql: error=[%s]\n", mysql_error(db));
fatal_exit("hs_longrun_init_table");
}
mysql_do(db, "drop database if exists hstestdb");
mysql_do(db, "create database hstestdb");
mysql_do(db, "use hstestdb");
mysql_do(db,
"create table hstesttbl ("
"k int primary key,"
"v1 varchar(32) not null,"
"v2 varchar(32) not null,"
"v3 varchar(32) not null"
") character set utf8 collate utf8_bin engine = innodb");
for (int i = 0; i < num_prepare; ++i) {
const std::string i_str = to_stdstring(i);
const std::string v1 = "pv1_" + i_str;
const std::string v2 = "pv2_" + i_str;
const std::string v3 = "pv3_" + i_str;
char buf[1024];
snprintf(buf, 1024, "insert into hstesttbl(k, v1, v2, v3) values"
"(%d, '%s', '%s', '%s')", i, v1.c_str(), v2.c_str(), v3.c_str());
mysql_do(db, buf);
record_value *rec = shared.records[i];
rec->key = i_str;
rec->values.resize(4);
rec->values[0] = i_str;
rec->values[1] = v1;
rec->values[2] = v2;
rec->values[3] = v3;
rec->deleted = false;
}
}
int
hs_longrun_main(int argc, char **argv)
{
hs_longrun_shared shared;
parse_args(argc, argv, shared.conf);
shared.conf["host"] = shared.conf.get_str("host", "localhost");
shared.verbose = shared.conf.get_int("verbose", 1);
const int table_size = shared.conf.get_int("table_size", 10000);
for (int i = 0; i < table_size; ++i) {
std::auto_ptr<record_value> rec(new record_value());
rec->key = to_stdstring(i);
shared.records.push_back_ptr(rec);
}
mysql_library_init(0, 0, 0);
const int duration = shared.conf.get_int("duration", 10);
const int num_hsinsert = shared.conf.get_int("num_hsinsert", 10);
const int num_hsdelete = shared.conf.get_int("num_hsdelete", 10);
const int num_hsupdate = shared.conf.get_int("num_hsupdate", 10);
const int num_hsread = shared.conf.get_int("num_hsread", 10);
const int num_myread = shared.conf.get_int("num_myread", 10);
const int num_mydelins = shared.conf.get_int("num_mydelins", 10);
int num_hsreadnolock = shared.conf.get_int("num_hsreadnolock", 10);
const bool always_filled = (num_hsinsert == 0 && num_hsdelete == 0);
if (!always_filled) {
num_hsreadnolock = 0;
}
hs_longrun_init_table(shared.conf, always_filled ? table_size : 0,
shared);
/* create worker threads */
static const struct thrtmpl_type {
const char *type; char op; int num; int hs; int lock;
} thrtmpl[] = {
{ "hsinsert", 'I', num_hsinsert, 1, 1 },
{ "hsdelete", 'D', num_hsdelete, 1, 1 },
{ "hsupdate", 'U', num_hsupdate, 1, 1 },
{ "hsread", 'R', num_hsread, 1, 1 },
{ "hsreadnolock", 'N', num_hsreadnolock, 1, 0 },
{ "myread", 'R', num_myread, 0, 1 },
{ "mydelins", 'T', num_mydelins, 0, 1 },
};
typedef auto_ptrcontainer< std::vector<hs_longrun_thread_base *> > thrs_type;
thrs_type thrs;
for (size_t i = 0; i < sizeof(thrtmpl)/sizeof(thrtmpl[0]); ++i) {
const thrtmpl_type& e = thrtmpl[i];
for (int j = 0; j < e.num; ++j) {
int id = thrs.size();
const hs_longrun_thread_hs::arg_type arg(id, e.type, e.op, e.lock,
shared);
std::auto_ptr<hs_longrun_thread_base> thr;
if (e.hs) {
thr.reset(new hs_longrun_thread_hs(arg));
} else {
thr.reset(new hs_longrun_thread_my(arg));
}
thrs.push_back_ptr(thr);
}
}
shared.num_threads = thrs.size();
/* start threads */
fprintf(stderr, "START\n");
shared.running = 1;
for (size_t i = 0; i < thrs.size(); ++i) {
thrs[i]->start();
}
/* wait */
sleep(duration);
/* stop thread */
shared.running = 0;
for (size_t i = 0; i < thrs.size(); ++i) {
thrs[i]->join();
}
fprintf(stderr, "DONE\n");
/* summary */
typedef std::map<std::string, hs_longrun_stat> stat_map;
stat_map sm;
for (size_t i = 0; i < thrs.size(); ++i) {
hs_longrun_thread_base *const thr = thrs[i];
const std::string wt = thr->arg.worker_type;
hs_longrun_stat& v = sm[wt];
v.add(thr->stat);
}
hs_longrun_stat total;
for (stat_map::const_iterator i = sm.begin(); i != sm.end(); ++i) {
if (i->second.verify_error_count != 0) {
fprintf(stderr, "%s verify_error %llu\n", i->first.c_str(),
i->second.verify_error_count);
}
if (i->second.runtime_error_count) {
fprintf(stderr, "%s runtime_error %llu\n", i->first.c_str(),
i->second.runtime_error_count);
}
if (i->second.unknown_count) {
fprintf(stderr, "%s unknown %llu\n", i->first.c_str(),
i->second.unknown_count);
}
fprintf(stderr, "%s success %llu\n", i->first.c_str(),
i->second.success_count);
total.add(i->second);
}
if (total.verify_error_count != 0) {
fprintf(stderr, "TOTAL verify_error %llu\n", total.verify_error_count);
}
if (total.runtime_error_count != 0) {
fprintf(stderr, "TOTAL runtime_error %llu\n", total.runtime_error_count);
}
if (total.unknown_count != 0) {
fprintf(stderr, "TOTAL unknown %llu\n", total.unknown_count);
}
fprintf(stderr, "TOTAL success %llu\n", total.success_count);
mysql_library_end();
return 0;
}
};
int
main(int argc, char **argv)
{
return dena::hs_longrun_main(argc, argv);
}
...@@ -92,7 +92,7 @@ namespace { ...@@ -92,7 +92,7 @@ namespace {
double double
gettimeofday_double() gettimeofday_double()
{ {
struct timeval tv = { }; struct timeval tv;
if (gettimeofday(&tv, 0) != 0) { if (gettimeofday(&tv, 0) != 0) {
fatal_abort("gettimeofday"); fatal_abort("gettimeofday");
} }
...@@ -552,7 +552,8 @@ hstest_thread::test_9(int test_num) ...@@ -552,7 +552,8 @@ hstest_thread::test_9(int test_num)
"moreflds_prefix", "column0123456789_"); "moreflds_prefix", "column0123456789_");
const int use_handler = arg.sh.conf.get_int("handler", 0); const int use_handler = arg.sh.conf.get_int("handler", 0);
const int sched_flag = arg.sh.conf.get_int("sched", 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"; std::string flds = "v";
for (int i = 0; i < moreflds; ++i) { for (int i = 0; i < moreflds; ++i) {
char buf[1024]; char buf[1024];
...@@ -561,6 +562,7 @@ hstest_thread::test_9(int test_num) ...@@ -561,6 +562,7 @@ hstest_thread::test_9(int test_num)
} }
int connected = 0; int connected = 0;
std::auto_ptr<auto_mysql_stmt> stmt; std::auto_ptr<auto_mysql_stmt> stmt;
string_buffer wbuf;
for (int i = 0; i < num; ++i) { for (int i = 0; i < num; ++i) {
const double tm1 = gettimeofday_double(); const double tm1 = gettimeofday_double();
const int flags = 0; const int flags = 0;
...@@ -623,6 +625,20 @@ hstest_thread::test_9(int test_num) ...@@ -623,6 +625,20 @@ hstest_thread::test_9(int test_num)
// TODO: moreflds // TODO: moreflds
} else if (ssps) { } 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 { } else {
buf_query_len = snprintf(buf_query, sizeof(buf_query), buf_query_len = snprintf(buf_query, sizeof(buf_query),
"select %s from hstest_table1 where k = '%d'", flds.c_str(), k); "select %s from hstest_table1 where k = '%d'", flds.c_str(), k);
...@@ -651,6 +667,8 @@ hstest_thread::test_9(int test_num) ...@@ -651,6 +667,8 @@ hstest_thread::test_9(int test_num)
} }
r = mysql_stmt_execute(*stmt); r = mysql_stmt_execute(*stmt);
// fprintf(stderr, "stmt exec\n"); // fprintf(stderr, "stmt exec\n");
} else if (use_in) {
r = mysql_real_query(db, wbuf.begin(), wbuf.size());
} else { } else {
r = mysql_real_query(db, buf_query, buf_query_len); r = mysql_real_query(db, buf_query, buf_query_len);
// fprintf(stderr, "real query\n"); // fprintf(stderr, "real query\n");
...@@ -694,7 +712,7 @@ hstest_thread::test_9(int test_num) ...@@ -694,7 +712,7 @@ hstest_thread::test_9(int test_num)
num_flds = mysql_num_fields(res); num_flds = mysql_num_fields(res);
MYSQL_ROW row = 0; MYSQL_ROW row = 0;
while ((row = mysql_fetch_row(res)) != 0) { while ((row = mysql_fetch_row(res)) != 0) {
got_data = 1; got_data += 1;
unsigned long *const lengths = mysql_fetch_lengths(res); unsigned long *const lengths = mysql_fetch_lengths(res);
if (verbose >= 2) { if (verbose >= 2) {
for (unsigned int i = 0; i < num_flds; ++i) { for (unsigned int i = 0; i < num_flds; ++i) {
...@@ -706,7 +724,10 @@ hstest_thread::test_9(int test_num) ...@@ -706,7 +724,10 @@ hstest_thread::test_9(int test_num)
} }
} }
} else { } else {
got_data = 1; MYSQL_ROW row = 0;
while ((row = mysql_fetch_row(res)) != 0) {
got_data += 1;
}
} }
} else { } else {
if (mysql_field_count(db) == 0) { if (mysql_field_count(db) == 0) {
...@@ -730,7 +751,7 @@ hstest_thread::test_9(int test_num) ...@@ -730,7 +751,7 @@ hstest_thread::test_9(int test_num)
if (err == 0) { if (err == 0) {
++io_success_count; ++io_success_count;
if (num_affected_rows > 0 || got_data > 0) { if (num_affected_rows > 0 || got_data > 0) {
++op_success_count; op_success_count += got_data;
} else { } else {
if (verbose >= 1) { if (verbose >= 1) {
fprintf(stderr, "k=%d numaff=%u gotdata=%d\n", fprintf(stderr, "k=%d numaff=%u gotdata=%d\n",
...@@ -779,6 +800,7 @@ hstest_thread::test_10(int test_num) ...@@ -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 table = arg.sh.conf.get_str("table", "hstest_table1");
const std::string index = arg.sh.conf.get_str("index", "PRIMARY"); const std::string index = arg.sh.conf.get_str("index", "PRIMARY");
const std::string field = arg.sh.conf.get_str("field", "v"); 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( const std::string moreflds_prefix = arg.sh.conf.get_str(
"moreflds_prefix", "column0123456789_"); "moreflds_prefix", "column0123456789_");
const int dump = arg.sh.dump; const int dump = arg.sh.dump;
...@@ -789,8 +811,8 @@ hstest_thread::test_10(int test_num) ...@@ -789,8 +811,8 @@ hstest_thread::test_10(int test_num)
snprintf(sbuf, sizeof(sbuf), ",%s%d", moreflds_prefix.c_str(), i); snprintf(sbuf, sizeof(sbuf), ",%s%d", moreflds_prefix.c_str(), i);
moreflds_str += std::string(sbuf); moreflds_str += std::string(sbuf);
} }
char wbuf[16384], rbuf[16384]; string_buffer wbuf;
int wbuflen = 0; char rbuf[16384];
for (size_t i = 0; i < arg.sh.loop; ++i) { for (size_t i = 0; i < arg.sh.loop; ++i) {
int len = 0, rlen = 0, wlen = 0; int len = 0, rlen = 0, wlen = 0;
#if 0 #if 0
...@@ -801,15 +823,18 @@ hstest_thread::test_10(int test_num) ...@@ -801,15 +823,18 @@ hstest_thread::test_10(int test_num)
fprintf(stderr, "connect: %d %s\n", errno, strerror(errno)); fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
return; 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(), "P\t1\t%s\t%s\tPRIMARY\t%s%s\n", dbname.c_str(), table.c_str(),
field.c_str(), moreflds_str.c_str()); field.c_str(), moreflds_str.c_str());
/* pst_num, db, table, index, retflds */ /* 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) { if (len != wlen) {
fprintf(stderr, "write: %d %d\n", len, wlen); fprintf(stderr, "write: %d %d\n", len, wlen);
return; return;
} }
wbuf.clear();
rlen = read(fd.get(), rbuf, sizeof(rbuf)); rlen = read(fd.get(), rbuf, sizeof(rbuf));
if (rlen <= 0 || rbuf[rlen - 1] != '\n') { if (rlen <= 0 || rbuf[rlen - 1] != '\n') {
fprintf(stderr, "read: rlen=%d errno=%d\n", rlen, errno); fprintf(stderr, "read: rlen=%d errno=%d\n", rlen, errno);
...@@ -824,7 +849,6 @@ hstest_thread::test_10(int test_num) ...@@ -824,7 +849,6 @@ hstest_thread::test_10(int test_num)
const double tm1 = gettimeofday_double(); const double tm1 = gettimeofday_double();
for (size_t j = 0; j < arg.sh.pipe; ++j) { for (size_t j = 0; j < arg.sh.pipe; ++j) {
int k = 0, v = 0; int k = 0, v = 0;
wbuflen = 0;
{ {
while (true) { while (true) {
double kf = 0, vf = 0; double kf = 0, vf = 0;
...@@ -832,19 +856,6 @@ hstest_thread::test_10(int test_num) ...@@ -832,19 +856,6 @@ hstest_thread::test_10(int test_num)
drand48_r(&randbuf, &vf); drand48_r(&randbuf, &vf);
k = int(kf * tablesize) + firstkey; k = int(kf * tablesize) + firstkey;
v = int(vf * 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) { if (k - firstkey < arg.sh.keygen_size) {
volatile char *const ptr = arg.sh.keygen + (k - firstkey); volatile char *const ptr = arg.sh.keygen + (k - firstkey);
// int oldv = __sync_fetch_and_or(ptr, 1); // int oldv = __sync_fetch_and_or(ptr, 1);
...@@ -864,15 +875,42 @@ hstest_thread::test_10(int test_num) ...@@ -864,15 +875,42 @@ hstest_thread::test_10(int test_num)
continue; 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; 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_cnt = 0;
size_t read_pos = 0; size_t read_pos = 0;
while (read_cnt < arg.sh.pipe) { while (read_cnt < arg.sh.pipe) {
...@@ -922,7 +960,7 @@ hstest_thread::test_10(int test_num) ...@@ -922,7 +960,7 @@ hstest_thread::test_10(int test_num)
++op_success_count; ++op_success_count;
arg.sh.increment_count(); arg.sh.increment_count();
if (arg.sh.dump && arg.sh.pipe == 1) { 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 ...@@ -13,6 +13,12 @@ AC_PROG_CXX
AC_PROG_CPP AC_PROG_CPP
AC_PROG_LIBTOOL 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_DEFUN([CONFIG_OPTION_MYSQL],[
AC_MSG_CHECKING([mysql source]) AC_MSG_CHECKING([mysql source])
...@@ -66,8 +72,12 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[ ...@@ -66,8 +72,12 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[
fi fi
MYSQL_CFLAGS_ADD=`"$ac_mysql_config" --cflags` MYSQL_CFLAGS_ADD=`"$ac_mysql_config" --cflags`
MYSQL_CFLAGS="$MYSQL_CFLAGS $MYSQL_CFLAGS_ADD -DFORCE_DBUG_OFF" MYSQL_CFLAGS="$MYSQL_CFLAGS $MYSQL_CFLAGS_ADD"
# FIXME 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) AC_SUBST(MYSQL_CFLAGS)
MYSQL_BIN_VERSION=`"$ac_mysql_config" --version` MYSQL_BIN_VERSION=`"$ac_mysql_config" --version`
......
...@@ -80,8 +80,20 @@ handlersocket_accept_balance (default = 0, min = 0, max = 10000) ...@@ -80,8 +80,20 @@ handlersocket_accept_balance (default = 0, min = 0, max = 10000)
handlersocket_wrlock_timeout (default = 12, min = 0, max = 3600) handlersocket_wrlock_timeout (default = 12, min = 0, max = 3600)
Specify the lock timeout in seconds. When a write request is 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 'handlersocket_wr'. This option sets the timeout for the
locking. 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 ...@@ -11,7 +11,7 @@ Basic syntax
distinguish NULL from an empty string, as most DBMs does so. distinguish NULL from an empty string, as most DBMs does so.
- NULL is expressed as a single NUL(0x00). - NULL is expressed as a single NUL(0x00).
- An encoded string is a string with the following encoding rules. - 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 - A character in the range [0x00 - 0x0f] is prefixed by 0x01 and
shifted by 0x40. For example, 0x03 is encoded as 0x01 0x43. 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 - Note that a string can be empty. A continuation of 0x09 0x09 means that
...@@ -33,12 +33,14 @@ Request and Response ...@@ -33,12 +33,14 @@ Request and Response
The 'open_index' request has the following syntax. 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. - <indexid> is a number in decimal.
- <dbname>, <tablename>, and <indexname> are strings. To open the primary - <dbname>, <tablename>, and <indexname> are strings. To open the primary
key, use PRIMARY as <indexname>. key, use PRIMARY as <indexname>.
- <columns> is a comma-separated list of column names. - <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 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 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. ...@@ -51,8 +53,20 @@ For efficiency, keep <indexid> small as far as possible.
Getting data Getting data
The 'find' request has the following syntax. 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 - <indexid> is a number. This number must be an <indexid> specified by a
'open_index' request executed previously on the same connection. 'open_index' request executed previously on the same connection.
...@@ -60,30 +74,53 @@ The 'find' request has the following syntax. ...@@ -60,30 +74,53 @@ The 'find' request has the following syntax.
HandlerSocket supports '=', '>', '>=', '<', and '<='. HandlerSocket supports '=', '>', '>=', '<', and '<='.
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This - <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 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. - <v1> ... <vn> specify the index column values to fetch.
- <limit> and <offset> are numbers. These parameters can be omitted. When - LIM is optional. <limit> and <offset> are numbers. When omitted, it works
omitted, it works as if 1 and 0 are specified. 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 Updating/Deleting data
The 'find_modify' request has the following syntax. 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> ... - <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 <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 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 Inserting data
The 'insert' request has the following syntax. 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 - <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 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. ...@@ -91,6 +128,19 @@ The 'insert' request has the following syntax.
- <v1> ... <vn> specify the column values to set. For columns not in - <v1> ... <vn> specify the column values to set. For columns not in
<columns>, the default values for each column are set. <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 Response syntax
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define DBG_FLD(x) #define DBG_FLD(x)
#define DBG_FILTER(x) #define DBG_FILTER(x)
#define DBG_REFCNT(x) #define DBG_REFCNT(x)
#define DBG_KEYLEN(x)
#define DBG_DELETED #define DBG_DELETED
/* status variables */ /* status variables */
...@@ -140,10 +141,8 @@ struct dbcontext : public dbcontext_i, private noncopyable { ...@@ -140,10 +141,8 @@ struct dbcontext : public dbcontext_i, private noncopyable {
virtual void close_tables_if(); virtual void close_tables_if();
virtual void table_addref(size_t tbl_id); virtual void table_addref(size_t tbl_id);
virtual void table_release(size_t tbl_id); virtual void table_release(size_t tbl_id);
virtual void cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn, virtual void cmd_open(dbcallback_i& cb, const cmd_open_args& args);
const char *tbl, const char *idx, const char *retflds, virtual void cmd_exec(dbcallback_i& cb, const cmd_exec_args& args);
const char *filflds);
virtual void cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args);
virtual void set_statistics(size_t num_conns, size_t num_active); virtual void set_statistics(size_t num_conns, size_t num_active);
private: private:
int set_thread_message(const char *fmt, ...) int set_thread_message(const char *fmt, ...)
...@@ -184,11 +183,6 @@ struct dbcontext : public dbcontext_i, private noncopyable { ...@@ -184,11 +183,6 @@ struct dbcontext : public dbcontext_i, private noncopyable {
std::vector<char> info_message_buf; std::vector<char> info_message_buf;
table_vec_type table_vec; table_vec_type table_vec;
table_map_type table_map; table_map_type table_map;
#if MYSQL_VERSION_ID >= 50505
MDL_request *mdl_request;
#else
void *mdl_request;
#endif
}; };
database::database(const config& c) database::database(const config& c)
...@@ -227,7 +221,7 @@ database_i::create(const config& conf) ...@@ -227,7 +221,7 @@ database_i::create(const config& conf)
dbcontext::dbcontext(volatile database *d, bool for_write) dbcontext::dbcontext(volatile database *d, bool for_write)
: dbref(d), for_write_flag(for_write), thd(0), lock(0), lock_failed(false), : dbref(d), for_write_flag(for_write), thd(0), lock(0), lock_failed(false),
user_level_lock_timeout(0), user_level_lock_locked(false), user_level_lock_timeout(0), user_level_lock_locked(false),
commit_error(false), mdl_request(0) commit_error(false)
{ {
info_message_buf.resize(8192); info_message_buf.resize(8192);
user_level_lock_timeout = d->get_conf().get_int("wrlock_timeout", 12); user_level_lock_timeout = d->get_conf().get_int("wrlock_timeout", 12);
...@@ -274,6 +268,8 @@ wait_server_to_start(THD *thd, volatile int& shutdown_flag) ...@@ -274,6 +268,8 @@ wait_server_to_start(THD *thd, volatile int& shutdown_flag)
}; // namespace }; // namespace
#define DENA_THR_OFFSETOF(fld) ((char *)(&thd->fld) - (char *)thd)
void void
dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag) dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag)
{ {
...@@ -282,9 +278,17 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag) ...@@ -282,9 +278,17 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag)
my_thread_init(); my_thread_init();
thd = new THD; thd = new THD;
thd->thread_stack = (char *)stack_bottom; thd->thread_stack = (char *)stack_bottom;
DBG_THR(const size_t of = (char *)(&thd->thread_stack) - (char *)thd); DBG_THR(fprintf(stderr,
DBG_THR(fprintf(stderr, "thread_stack = %p sz=%zu of=%zu\n", "thread_stack = %p sizeof(THD)=%zu sizeof(mtx)=%zu "
thd->thread_stack, sizeof(THD), of)); "O: %zu %zu %zu %zu %zu %zu %zu\n",
thd->thread_stack, sizeof(THD), sizeof(LOCK_thread_count),
DENA_THR_OFFSETOF(mdl_context),
DENA_THR_OFFSETOF(net),
DENA_THR_OFFSETOF(LOCK_thd_data),
DENA_THR_OFFSETOF(mysys_var),
DENA_THR_OFFSETOF(stmt_arena),
DENA_THR_OFFSETOF(limit_found_rows),
DENA_THR_OFFSETOF(locked_tables_list)));
thd->store_globals(); thd->store_globals();
thd->system_thread = static_cast<enum_thread_type>(1<<30UL); thd->system_thread = static_cast<enum_thread_type>(1<<30UL);
memset(&thd->net, 0, sizeof(thd->net)); memset(&thd->net, 0, sizeof(thd->net));
...@@ -317,15 +321,6 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag) ...@@ -317,15 +321,6 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag)
set_thread_message("hs:listening"); set_thread_message("hs:listening");
DBG_THR(fprintf(stderr, "HNDSOCK x1 %p\n", thd)); DBG_THR(fprintf(stderr, "HNDSOCK x1 %p\n", thd));
#if MYSQL_VERSION_ID >= 50508
mdl_request = new(thd->mem_root) MDL_request;
mdl_request->init(MDL_key::TABLE, "", "",
for_write_flag ? MDL_SHARED_WRITE : MDL_SHARED_READ, MDL_STATEMENT);
#elif MYSQL_VERSION_ID >= 50505
mdl_request = MDL_request::create(MDL_key::TABLE, "", "",
for_write_flag ? MDL_SHARED_WRITE : MDL_SHARED_READ, thd->mem_root);
#endif
lex_start(thd); lex_start(thd);
user_lock.reset(new expr_user_lock(thd, user_level_lock_timeout)); user_lock.reset(new expr_user_lock(thd, user_level_lock_timeout));
...@@ -389,7 +384,7 @@ dbcontext::lock_tables_if() ...@@ -389,7 +384,7 @@ dbcontext::lock_tables_if()
} }
if (lock == 0) { if (lock == 0) {
const size_t num_max = table_vec.size(); const size_t num_max = table_vec.size();
TABLE *tables[num_max ? num_max : 1]; /* GNU */ TABLE **const tables = DENA_ALLOCA_ALLOCATE(TABLE *, num_max + 1);
size_t num_open = 0; size_t num_open = 0;
for (size_t i = 0; i < num_max; ++i) { for (size_t i = 0; i < num_max; ++i) {
if (table_vec[i].refcount > 0) { if (table_vec[i].refcount > 0) {
...@@ -420,6 +415,7 @@ dbcontext::lock_tables_if() ...@@ -420,6 +415,7 @@ dbcontext::lock_tables_if()
thd->current_stmt_binlog_row_based = 1; thd->current_stmt_binlog_row_based = 1;
#endif #endif
} }
DENA_ALLOCA_FREE(tables);
} }
DBG_LOCK(fprintf(stderr, "HNDSOCK tblnum=%d\n", (int)tblnum)); DBG_LOCK(fprintf(stderr, "HNDSOCK tblnum=%d\n", (int)tblnum));
} }
...@@ -428,14 +424,17 @@ void ...@@ -428,14 +424,17 @@ void
dbcontext::unlock_tables_if() dbcontext::unlock_tables_if()
{ {
if (lock != 0) { if (lock != 0) {
DENA_VERBOSE(100, fprintf(stderr, "HNDSOCK unlock tables\n")); DENA_VERBOSE(100, fprintf(stderr, "HNDSOCK unlock tables %p %p\n",
thd, thd->lock));
if (for_write_flag) { if (for_write_flag) {
for (size_t i = 0; i < table_vec.size(); ++i) { for (size_t i = 0; i < table_vec.size(); ++i) {
if (table_vec[i].modified) { if (table_vec[i].modified) {
query_cache_invalidate3(thd, table_vec[i].table, 0); query_cache_invalidate3(thd, table_vec[i].table, 1);
/* invalidate immediately */ table_vec[i].table->file->ha_release_auto_increment();
} }
} }
}
{
bool suc = true; bool suc = true;
#if MYSQL_VERSION_ID >= 50505 #if MYSQL_VERSION_ID >= 50505
suc = (trans_commit_stmt(thd) == 0); suc = (trans_commit_stmt(thd) == 0);
...@@ -476,9 +475,12 @@ void ...@@ -476,9 +475,12 @@ void
dbcontext::close_tables_if() dbcontext::close_tables_if()
{ {
unlock_tables_if(); unlock_tables_if();
DENA_VERBOSE(100, fprintf(stderr, "HNDSOCK close tables\n"));
close_thread_tables(thd);
#if MYSQL_VERSION_ID >= 50505
thd->mdl_context.release_transactional_locks();
#endif
if (!table_vec.empty()) { if (!table_vec.empty()) {
DENA_VERBOSE(100, fprintf(stderr, "HNDSOCK close tables\n"));
close_thread_tables(thd);
statistic_increment(close_tables_count, &LOCK_status); statistic_increment(close_tables_count, &LOCK_status);
table_vec.clear(); table_vec.clear();
table_map.clear(); table_map.clear();
...@@ -544,7 +546,6 @@ dbcontext::dump_record(dbcallback_i& cb, TABLE *const table, ...@@ -544,7 +546,6 @@ dbcontext::dump_record(dbcallback_i& cb, TABLE *const table,
Field *const fld = table->field[fn]; Field *const fld = table->field[fn];
if (fld->is_null()) { if (fld->is_null()) {
/* null */ /* null */
cb.dbcb_resp_entry(0, 0);
fprintf(stderr, "NULL"); fprintf(stderr, "NULL");
} else { } else {
fld->val_str(&rwpstr, &rwpstr); fld->val_str(&rwpstr, &rwpstr);
...@@ -621,9 +622,6 @@ dbcontext::modify_record(dbcallback_i& cb, TABLE *const table, ...@@ -621,9 +622,6 @@ dbcontext::modify_record(dbcallback_i& cb, TABLE *const table,
if ((pval < 0 && nval > 0) || (pval > 0 && nval < 0)) { if ((pval < 0 && nval > 0) || (pval > 0 && nval < 0)) {
break; /* don't modify */ break; /* don't modify */
} }
if ((pval < 0) != (nval < 0)) {
nval = 0; /* crip */
}
} }
fld->store(nval, false); fld->store(nval, false);
} }
...@@ -649,7 +647,7 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -649,7 +647,7 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst,
} }
lock_tables_if(); lock_tables_if();
if (lock == 0) { if (lock == 0) {
return cb.dbcb_resp_short(2, "lock_tables"); return cb.dbcb_resp_short(1, "lock_tables");
} }
if (pst.get_table_id() >= table_vec.size()) { if (pst.get_table_id() >= table_vec.size()) {
return cb.dbcb_resp_short(2, "tblnum"); return cb.dbcb_resp_short(2, "tblnum");
...@@ -659,20 +657,30 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -659,20 +657,30 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst,
uchar *const buf = table->record[0]; uchar *const buf = table->record[0];
empty_record(table); empty_record(table);
memset(buf, 0, table->s->null_bytes); /* clear null flags */ memset(buf, 0, table->s->null_bytes); /* clear null flags */
Field **fld = table->field; const prep_stmt::fields_type& rf = pst.get_ret_fields();
size_t i = 0; const size_t n = rf.size();
for (; *fld && i < fvalslen; ++fld, ++i) { for (size_t i = 0; i < n; ++i) {
uint32_t fn = rf[i];
Field *const fld = table->field[fn];
if (fvals[i].begin() == 0) { if (fvals[i].begin() == 0) {
(*fld)->set_null(); fld->set_null();
} else { } else {
(*fld)->store(fvals[i].begin(), fvals[i].size(), &my_charset_bin); fld->store(fvals[i].begin(), fvals[i].size(), &my_charset_bin);
} }
} }
table->next_number_field = table->found_next_number_field; table->next_number_field = table->found_next_number_field;
/* FIXME: test */
const int r = hnd->ha_write_row(buf); const int r = hnd->ha_write_row(buf);
const ulonglong insert_id = table->file->insert_id_for_cur_row;
table->next_number_field = 0; table->next_number_field = 0;
table_vec[pst.get_table_id()].modified = true; table_vec[pst.get_table_id()].modified = true;
return cb.dbcb_resp_short(r != 0 ? 1 : 0, ""); if (r == 0 && table->found_next_number_field != 0) {
return cb.dbcb_resp_short_num64(0, insert_id);
}
if (r != 0) {
return cb.dbcb_resp_short_num(1, r);
}
return cb.dbcb_resp_short(0, "");
} }
void void
...@@ -685,6 +693,35 @@ dbcontext::cmd_sql_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -685,6 +693,35 @@ dbcontext::cmd_sql_internal(dbcallback_i& cb, const prep_stmt& pst,
return cb.dbcb_resp_short(2, "notimpl"); return cb.dbcb_resp_short(2, "notimpl");
} }
static size_t
prepare_keybuf(const cmd_exec_args& args, uchar *key_buf, TABLE *table,
KEY& kinfo, size_t invalues_index)
{
size_t kplen_sum = 0;
DBG_KEY(fprintf(stderr, "SLOW\n"));
for (size_t i = 0; i < args.kvalslen; ++i) {
const KEY_PART_INFO & kpt = kinfo.key_part[i];
string_ref kval = args.kvals[i];
if (args.invalues_keypart >= 0 &&
static_cast<size_t>(args.invalues_keypart) == i) {
kval = args.invalues[invalues_index];
}
if (kval.begin() == 0) {
kpt.field->set_null();
} else {
kpt.field->set_notnull();
}
kpt.field->store(kval.begin(), kval.size(), &my_charset_bin);
kplen_sum += kpt.store_length;
DBG_KEYLEN(fprintf(stderr, "l=%u sl=%zu\n", kpt.length,
kpt.store_length));
}
key_copy(key_buf, table->record[0], &kinfo, kplen_sum);
DBG_KEYLEN(fprintf(stderr, "sum=%zu flen=%u\n", kplen_sum,
kinfo.key_length));
return kplen_sum;
}
void void
dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
ha_rkey_function find_flag, const cmd_exec_args& args) ha_rkey_function find_flag, const cmd_exec_args& args)
...@@ -714,7 +751,7 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -714,7 +751,7 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
} }
lock_tables_if(); lock_tables_if();
if (lock == 0) { if (lock == 0) {
return cb.dbcb_resp_short(2, "lock_tables"); return cb.dbcb_resp_short(1, "lock_tables");
} }
if (pst.get_table_id() >= table_vec.size()) { if (pst.get_table_id() >= table_vec.size()) {
return cb.dbcb_resp_short(2, "tblnum"); return cb.dbcb_resp_short(2, "tblnum");
...@@ -728,30 +765,15 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -728,30 +765,15 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
if (args.kvalslen > kinfo.key_parts) { if (args.kvalslen > kinfo.key_parts) {
return cb.dbcb_resp_short(2, "kpnum"); return cb.dbcb_resp_short(2, "kpnum");
} }
uchar key_buf[kinfo.key_length]; /* GNU */ uchar *const key_buf = DENA_ALLOCA_ALLOCATE(uchar, kinfo.key_length);
size_t kplen_sum = 0; size_t invalues_idx = 0;
{ size_t kplen_sum = prepare_keybuf(args, key_buf, table, kinfo, invalues_idx);
DBG_KEY(fprintf(stderr, "SLOW\n"));
for (size_t i = 0; i < args.kvalslen; ++i) {
const KEY_PART_INFO & kpt = kinfo.key_part[i];
const string_ref& kval = args.kvals[i];
if (kval.begin() == 0) {
kpt.field->set_null();
} else {
kpt.field->set_notnull();
}
kpt.field->store(kval.begin(), kval.size(), &my_charset_bin);
kplen_sum += kpt.length;
}
key_copy(key_buf, table->record[0], &kinfo, kplen_sum);
}
/* filters */ /* filters */
uchar *filter_buf = 0; uchar *filter_buf = 0;
if (args.filters != 0) { if (args.filters != 0) {
const size_t filter_buf_len = calc_filter_buf_size(table, pst, const size_t filter_buf_len = calc_filter_buf_size(table, pst,
args.filters); args.filters);
filter_buf = reinterpret_cast<uchar *>(alloca(filter_buf_len)); filter_buf = DENA_ALLOCA_ALLOCATE(uchar, filter_buf_len);
/* FIXME: TEST */
if (!fill_filter_buf(table, pst, args.filters, filter_buf, if (!fill_filter_buf(table, pst, args.filters, filter_buf,
filter_buf_len)) { filter_buf_len)) {
return cb.dbcb_resp_short(2, "filterblob"); return cb.dbcb_resp_short(2, "filterblob");
...@@ -765,9 +787,6 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -765,9 +787,6 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
} }
hnd->ha_index_or_rnd_end(); hnd->ha_index_or_rnd_end();
hnd->ha_index_init(pst.get_idxnum(), 1); hnd->ha_index_init(pst.get_idxnum(), 1);
#if 0
statistic_increment(index_exec_count, &LOCK_status);
#endif
if (need_resp_record) { if (need_resp_record) {
cb.dbcb_resp_begin(pst.get_ret_fields().size()); cb.dbcb_resp_begin(pst.get_ret_fields().size());
} }
...@@ -775,8 +794,17 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -775,8 +794,17 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
uint32_t skip = args.skip; uint32_t skip = args.skip;
size_t modified_count = 0; size_t modified_count = 0;
int r = 0; int r = 0;
for (uint32_t i = 0; i < limit + skip; ++i) { bool is_first = true;
if (i == 0) { for (uint32_t cnt = 0; cnt < limit + skip;) {
if (is_first) {
is_first = false;
const key_part_map kpm = (1U << args.kvalslen) - 1;
r = hnd->ha_index_read_map(table->record[0], key_buf, kpm, find_flag);
} else if (args.invalues_keypart >= 0) {
if (++invalues_idx >= args.invalueslen) {
break;
}
kplen_sum = prepare_keybuf(args, key_buf, table, kinfo, invalues_idx);
const key_part_map kpm = (1U << args.kvalslen) - 1; const key_part_map kpm = (1U << args.kvalslen) - 1;
r = hnd->ha_index_read_map(table->record[0], key_buf, kpm, find_flag); r = hnd->ha_index_read_map(table->record[0], key_buf, kpm, find_flag);
} else { } else {
...@@ -814,12 +842,17 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -814,12 +842,17 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
} else if (skip > 0) { } else if (skip > 0) {
--skip; --skip;
} else { } else {
/* hit */
if (need_resp_record) { if (need_resp_record) {
resp_record(cb, table, pst); resp_record(cb, table, pst);
} }
if (mod_op != 0) { if (mod_op != 0) {
r = modify_record(cb, table, pst, args, mod_op, modified_count); r = modify_record(cb, table, pst, args, mod_op, modified_count);
} }
++cnt;
}
if (args.invalues_keypart >= 0 && r == HA_ERR_KEY_NOT_FOUND) {
continue;
} }
if (r != 0 && r != HA_ERR_RECORD_DELETED) { if (r != 0 && r != HA_ERR_RECORD_DELETED) {
break; break;
...@@ -833,7 +866,7 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -833,7 +866,7 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
/* revert dbcb_resp_begin() and dbcb_resp_entry() */ /* revert dbcb_resp_begin() and dbcb_resp_entry() */
cb.dbcb_resp_cancel(); cb.dbcb_resp_cancel();
} }
cb.dbcb_resp_short_num(2, r); cb.dbcb_resp_short_num(1, r);
} else { } else {
/* succeeded */ /* succeeded */
if (need_resp_record) { if (need_resp_record) {
...@@ -842,6 +875,8 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst, ...@@ -842,6 +875,8 @@ dbcontext::cmd_find_internal(dbcallback_i& cb, const prep_stmt& pst,
cb.dbcb_resp_short_num(0, modified_count); cb.dbcb_resp_short_num(0, modified_count);
} }
} }
DENA_ALLOCA_FREE(filter_buf);
DENA_ALLOCA_FREE(key_buf);
} }
size_t size_t
...@@ -856,6 +891,9 @@ dbcontext::calc_filter_buf_size(TABLE *table, const prep_stmt& pst, ...@@ -856,6 +891,9 @@ dbcontext::calc_filter_buf_size(TABLE *table, const prep_stmt& pst,
const uint32_t fn = pst.get_filter_fields()[f->ff_offset]; const uint32_t fn = pst.get_filter_fields()[f->ff_offset];
filter_buf_len += table->field[fn]->pack_length(); filter_buf_len += table->field[fn]->pack_length();
} }
++filter_buf_len;
/* Field_medium::cmp() calls uint3korr(), which may read 4 bytes.
Allocate 1 more byte for safety. */
return filter_buf_len; return filter_buf_len;
} }
...@@ -954,11 +992,11 @@ dbcontext::check_filter(dbcallback_i& cb, TABLE *table, const prep_stmt& pst, ...@@ -954,11 +992,11 @@ dbcontext::check_filter(dbcallback_i& cb, TABLE *table, const prep_stmt& pst,
} }
void void
dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn, dbcontext::cmd_open(dbcallback_i& cb, const cmd_open_args& arg)
const char *tbl, const char *idx, const char *retflds, const char *filflds)
{ {
unlock_tables_if(); unlock_tables_if();
const table_name_type k = std::make_pair(std::string(dbn), std::string(tbl)); const table_name_type k = std::make_pair(std::string(arg.dbn),
std::string(arg.tbl));
const table_map_type::const_iterator iter = table_map.find(k); const table_map_type::const_iterator iter = table_map.find(k);
uint32_t tblnum = 0; uint32_t tblnum = 0;
if (iter != table_map.end()) { if (iter != table_map.end()) {
...@@ -971,23 +1009,24 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn, ...@@ -971,23 +1009,24 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn,
bool refresh = true; bool refresh = true;
const thr_lock_type lock_type = for_write_flag ? TL_WRITE : TL_READ; const thr_lock_type lock_type = for_write_flag ? TL_WRITE : TL_READ;
#if MYSQL_VERSION_ID >= 50505 #if MYSQL_VERSION_ID >= 50505
tables.init_one_table(dbn, strlen(dbn), tbl, strlen(tbl), tbl, tables.init_one_table(arg.dbn, strlen(arg.dbn), arg.tbl, strlen(arg.tbl),
lock_type); arg.tbl, lock_type);
tables.mdl_request = mdl_request; tables.mdl_request.init(MDL_key::TABLE, arg.dbn, arg.tbl,
Open_table_context ot_act(thd, MYSQL_OPEN_REOPEN); for_write_flag ? MDL_SHARED_WRITE : MDL_SHARED_READ, MDL_TRANSACTION);
Open_table_context ot_act(thd, 0);
if (!open_table(thd, &tables, thd->mem_root, &ot_act)) { if (!open_table(thd, &tables, thd->mem_root, &ot_act)) {
table = tables.table; table = tables.table;
} }
#else #else
tables.init_one_table(dbn, tbl, lock_type); tables.init_one_table(arg.dbn, arg.tbl, lock_type);
table = open_table(thd, &tables, thd->mem_root, &refresh, table = open_table(thd, &tables, thd->mem_root, &refresh,
OPEN_VIEW_NO_PARSE); OPEN_VIEW_NO_PARSE);
#endif #endif
if (table == 0) { if (table == 0) {
DENA_VERBOSE(10, fprintf(stderr, DENA_VERBOSE(20, fprintf(stderr,
"HNDSOCK failed to open %p [%s] [%s] [%d]\n", "HNDSOCK failed to open %p [%s] [%s] [%d]\n",
thd, dbn, tbl, static_cast<int>(refresh))); thd, arg.dbn, arg.tbl, static_cast<int>(refresh)));
return cb.dbcb_resp_short(2, "open_table"); return cb.dbcb_resp_short(1, "open_table");
} }
statistic_increment(open_tables_count, &LOCK_status); statistic_increment(open_tables_count, &LOCK_status);
table->reginfo.lock_type = lock_type; table->reginfo.lock_type = lock_type;
...@@ -999,15 +1038,16 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn, ...@@ -999,15 +1038,16 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn,
table_map[k] = tblnum; table_map[k] = tblnum;
} }
size_t idxnum = static_cast<size_t>(-1); size_t idxnum = static_cast<size_t>(-1);
if (idx[0] >= '0' && idx[0] <= '9') { if (arg.idx[0] >= '0' && arg.idx[0] <= '9') {
/* numeric */ /* numeric */
TABLE *const table = table_vec[tblnum].table; TABLE *const table = table_vec[tblnum].table;
idxnum = atoi(idx); idxnum = atoi(arg.idx);
if (idxnum >= table->s->keys) { if (idxnum >= table->s->keys) {
return cb.dbcb_resp_short(2, "idxnum"); return cb.dbcb_resp_short(2, "idxnum");
} }
} else { } else {
const char *const idx_name_to_open = idx[0] == '\0' ? "PRIMARY" : idx; const char *const idx_name_to_open =
arg.idx[0] == '\0' ? "PRIMARY" : arg.idx;
TABLE *const table = table_vec[tblnum].table; TABLE *const table = table_vec[tblnum].table;
for (uint i = 0; i < table->s->keys; ++i) { for (uint i = 0; i < table->s->keys; ++i) {
KEY& kinfo = table->key_info[i]; KEY& kinfo = table->key_info[i];
...@@ -1022,14 +1062,14 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn, ...@@ -1022,14 +1062,14 @@ dbcontext::cmd_open_index(dbcallback_i& cb, size_t pst_id, const char *dbn,
} }
prep_stmt::fields_type rf; prep_stmt::fields_type rf;
prep_stmt::fields_type ff; prep_stmt::fields_type ff;
if (!parse_fields(table_vec[tblnum].table, retflds, rf)) { if (!parse_fields(table_vec[tblnum].table, arg.retflds, rf)) {
return cb.dbcb_resp_short(2, "fld"); return cb.dbcb_resp_short(2, "fld");
} }
if (!parse_fields(table_vec[tblnum].table, filflds, ff)) { if (!parse_fields(table_vec[tblnum].table, arg.filflds, ff)) {
return cb.dbcb_resp_short(2, "fld"); return cb.dbcb_resp_short(2, "fld");
} }
prep_stmt p(this, tblnum, idxnum, rf, ff); prep_stmt p(this, tblnum, idxnum, rf, ff);
cb.dbcb_set_prep_stmt(pst_id, p); cb.dbcb_set_prep_stmt(arg.pst_id, p);
return cb.dbcb_resp_short(0, ""); return cb.dbcb_resp_short(0, "");
} }
...@@ -1070,7 +1110,7 @@ enum db_write_op { ...@@ -1070,7 +1110,7 @@ enum db_write_op {
}; };
void void
dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args) dbcontext::cmd_exec(dbcallback_i& cb, const cmd_exec_args& args)
{ {
const prep_stmt& p = *args.pst; const prep_stmt& p = *args.pst;
if (p.get_table_id() == static_cast<size_t>(-1)) { if (p.get_table_id() == static_cast<size_t>(-1)) {
...@@ -1096,7 +1136,7 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args) ...@@ -1096,7 +1136,7 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
wrop = db_write_op_sql; wrop = db_write_op_sql;
break; break;
default: default:
return cb.dbcb_resp_short(1, "op"); return cb.dbcb_resp_short(2, "op");
} }
} else if (args.op.size() == 2 && args.op.begin()[1] == '=') { } else if (args.op.size() == 2 && args.op.begin()[1] == '=') {
switch (args.op.begin()[0]) { switch (args.op.begin()[0]) {
...@@ -1107,10 +1147,10 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args) ...@@ -1107,10 +1147,10 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
find_flag = HA_READ_KEY_OR_PREV; find_flag = HA_READ_KEY_OR_PREV;
break; break;
default: default:
return cb.dbcb_resp_short(1, "op"); return cb.dbcb_resp_short(2, "op");
} }
} else { } else {
return cb.dbcb_resp_short(1, "op"); return cb.dbcb_resp_short(2, "op");
} }
if (args.kvalslen <= 0) { if (args.kvalslen <= 0) {
return cb.dbcb_resp_short(2, "klen"); return cb.dbcb_resp_short(2, "klen");
...@@ -1128,7 +1168,6 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args) ...@@ -1128,7 +1168,6 @@ dbcontext::cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
void void
dbcontext::set_statistics(size_t num_conns, size_t num_active) dbcontext::set_statistics(size_t num_conns, size_t num_active)
{ {
thd_proc_info(thd, &info_message_buf[0]);
if (for_write_flag) { if (for_write_flag) {
set_thread_message("handlersocket: mode=wr, %zu conns, %zu active", set_thread_message("handlersocket: mode=wr, %zu conns, %zu active",
num_conns, num_active); num_conns, num_active);
...@@ -1136,6 +1175,12 @@ dbcontext::set_statistics(size_t num_conns, size_t num_active) ...@@ -1136,6 +1175,12 @@ dbcontext::set_statistics(size_t num_conns, size_t num_active)
set_thread_message("handlersocket: mode=rd, %zu conns, %zu active", set_thread_message("handlersocket: mode=rd, %zu conns, %zu active",
num_conns, num_active); num_conns, num_active);
} }
/*
Don't set message buf if it's already in use. This saves slow call to
thd_proc_info() (if profiling is enabled)
*/
if (thd->proc_info != &info_message_buf[0])
thd_proc_info(thd, &info_message_buf[0]);
} }
}; };
......
...@@ -62,6 +62,7 @@ struct dbcallback_i { ...@@ -62,6 +62,7 @@ struct dbcallback_i {
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const = 0; 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(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_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_begin(size_t num_flds) = 0;
virtual void dbcb_resp_entry(const char *fld, size_t fldlen) = 0; virtual void dbcb_resp_entry(const char *fld, size_t fldlen) = 0;
virtual void dbcb_resp_end() = 0; virtual void dbcb_resp_end() = 0;
...@@ -81,6 +82,17 @@ struct record_filter { ...@@ -81,6 +82,17 @@ struct record_filter {
record_filter() : filter_type(record_filter_type_skip), ff_offset(0) { } 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 { struct cmd_exec_args {
const prep_stmt *pst; const prep_stmt *pst;
string_ref op; string_ref op;
...@@ -91,8 +103,11 @@ struct cmd_exec_args { ...@@ -91,8 +103,11 @@ struct cmd_exec_args {
string_ref mod_op; string_ref mod_op;
const string_ref *uvals; /* size must be pst->retfieelds.size() */ const string_ref *uvals; /* size must be pst->retfieelds.size() */
const record_filter *filters; 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), 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 { struct dbcontext_i {
...@@ -108,11 +123,8 @@ struct dbcontext_i { ...@@ -108,11 +123,8 @@ struct dbcontext_i {
virtual void close_tables_if() = 0; virtual void close_tables_if() = 0;
virtual void table_addref(size_t tbl_id) = 0; /* TODO: hide */ virtual void table_addref(size_t tbl_id) = 0; /* TODO: hide */
virtual void table_release(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, virtual void cmd_open(dbcallback_i& cb, const cmd_open_args& args) = 0;
const char *tbl, const char *idx, const char *retflds, virtual void cmd_exec(dbcallback_i& cb, const cmd_exec_args& args) = 0;
const char *filflds) = 0;
virtual void cmd_exec_on_index(dbcallback_i& cb, const cmd_exec_args& args)
= 0;
virtual void set_statistics(size_t num_conns, size_t num_active) = 0; virtual void set_statistics(size_t num_conns, size_t num_active) = 0;
}; };
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define DBG_FD(x) #define DBG_FD(x)
#define DBG_TR(x) #define DBG_TR(x)
#define DBG_EP(x) #define DBG_EP(x)
#define DBG_MULTI(x)
/* TODO */ /* TODO */
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(MSG_NOSIGNAL) #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(MSG_NOSIGNAL)
...@@ -40,13 +41,15 @@ struct dbconnstate { ...@@ -40,13 +41,15 @@ struct dbconnstate {
string_buffer writebuf; string_buffer writebuf;
std::vector<prep_stmt> prep_stmts; std::vector<prep_stmt> prep_stmts;
size_t resp_begin_pos; size_t resp_begin_pos;
size_t find_nl_pos;
void reset() { void reset() {
readbuf.clear(); readbuf.clear();
writebuf.clear(); writebuf.clear();
prep_stmts.clear(); prep_stmts.clear();
resp_begin_pos = 0; 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; struct hstcpsvr_conn;
...@@ -78,6 +81,7 @@ struct hstcpsvr_conn : public dbcallback_i { ...@@ -78,6 +81,7 @@ struct hstcpsvr_conn : public dbcallback_i {
virtual const prep_stmt *dbcb_get_prep_stmt(size_t pst_id) const; 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(uint32_t code, const char *msg);
virtual void dbcb_resp_short_num(uint32_t code, uint32_t value); 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_begin(size_t num_flds);
virtual void dbcb_resp_entry(const char *fld, size_t fldlen); virtual void dbcb_resp_entry(const char *fld, size_t fldlen);
virtual void dbcb_resp_end(); virtual void dbcb_resp_end();
...@@ -205,6 +209,15 @@ hstcpsvr_conn::dbcb_resp_short_num(uint32_t code, uint32_t value) ...@@ -205,6 +209,15 @@ hstcpsvr_conn::dbcb_resp_short_num(uint32_t code, uint32_t value)
cstate.writebuf.append_literal("\n"); 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 void
hstcpsvr_conn::dbcb_resp_begin(size_t num_flds) hstcpsvr_conn::dbcb_resp_begin(size_t num_flds)
{ {
...@@ -256,6 +269,7 @@ struct hstcpsvr_worker : public hstcpsvr_worker_i, private noncopyable { ...@@ -256,6 +269,7 @@ struct hstcpsvr_worker : public hstcpsvr_worker_i, private noncopyable {
#endif #endif
bool accept_enabled; bool accept_enabled;
int accept_balance; int accept_balance;
std::vector<string_ref> invalues_work;
std::vector<record_filter> filters_work; std::vector<record_filter> filters_work;
private: private:
int run_one_nb(); int run_one_nb();
...@@ -385,6 +399,7 @@ hstcpsvr_worker::run_one_nb() ...@@ -385,6 +399,7 @@ hstcpsvr_worker::run_one_nb()
vshared.shutdown = 1; vshared.shutdown = 1;
} else if (ch == '/') { } else if (ch == '/') {
conn.cstate.readbuf.clear(); conn.cstate.readbuf.clear();
conn.cstate.find_nl_pos = 0;
conn.cstate.writebuf.clear(); conn.cstate.writebuf.clear();
conn.read_finished = true; conn.read_finished = true;
conn.write_finished = true; conn.write_finished = true;
...@@ -533,6 +548,7 @@ hstcpsvr_worker::run_one_ep() ...@@ -533,6 +548,7 @@ hstcpsvr_worker::run_one_ep()
vshared.shutdown = 1; vshared.shutdown = 1;
} else if (ch == '/') { } else if (ch == '/') {
conn->cstate.readbuf.clear(); conn->cstate.readbuf.clear();
conn->cstate.find_nl_pos = 0;
conn->cstate.writebuf.clear(); conn->cstate.writebuf.clear();
conn->read_finished = true; conn->read_finished = true;
conn->write_finished = true; conn->write_finished = true;
...@@ -641,19 +657,24 @@ hstcpsvr_worker::run_one_ep() ...@@ -641,19 +657,24 @@ hstcpsvr_worker::run_one_ep()
void void
hstcpsvr_worker::execute_lines(hstcpsvr_conn& conn) hstcpsvr_worker::execute_lines(hstcpsvr_conn& conn)
{ {
DBG_MULTI(int cnt = 0);
dbconnstate& cstate = conn.cstate; dbconnstate& cstate = conn.cstate;
char *buf_end = cstate.readbuf.end(); char *buf_end = cstate.readbuf.end();
char *line_begin = cstate.readbuf.begin(); char *line_begin = cstate.readbuf.begin();
char *find_pos = line_begin + cstate.find_nl_pos;
while (true) { 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) { if (nl == 0) {
break; break;
} }
char *const lf = (line_begin != nl && nl[-1] == '\r') ? nl - 1 : nl; char *const lf = (line_begin != nl && nl[-1] == '\r') ? nl - 1 : nl;
DBG_MULTI(cnt++);
execute_line(line_begin, lf, conn); 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.readbuf.erase_front(line_begin - cstate.readbuf.begin());
cstate.find_nl_pos = cstate.readbuf.size();
DBG_MULTI(fprintf(stderr, "cnt=%d\n", cnt));
} }
void void
...@@ -721,8 +742,14 @@ hstcpsvr_worker::do_open_index(char *start, char *finish, hstcpsvr_conn& conn) ...@@ -721,8 +742,14 @@ hstcpsvr_worker::do_open_index(char *start, char *finish, hstcpsvr_conn& conn)
idxname_end[0] = 0; idxname_end[0] = 0;
retflds_end[0] = 0; retflds_end[0] = 0;
filflds_end[0] = 0; filflds_end[0] = 0;
return dbctx->cmd_open_index(conn, pst_id, dbname_begin, tblname_begin, cmd_open_args args;
idxname_begin, retflds_begin, filflds_begin); 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 void
...@@ -741,7 +768,8 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start, ...@@ -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); args.op = string_ref(op_begin, op_end);
skip_one(start, finish); skip_one(start, finish);
const uint32_t fldnum = read_ui32(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.kvals = flds;
args.kvalslen = fldnum; args.kvalslen = fldnum;
for (size_t i = 0; i < fldnum; ++i) { 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, ...@@ -765,10 +793,39 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
args.skip = read_ui32(start, finish); args.skip = read_ui32(start, finish);
if (start == finish) { if (start == finish) {
/* simple query */ /* 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); 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 */ /* filters */
size_t filters_count = 0; size_t filters_count = 0;
while (start != finish && (start[0] == 'W' || start[0] == 'F')) { 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, ...@@ -823,7 +880,7 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
} }
if (start == finish) { if (start == finish) {
/* no modops */ /* no modops */
return dbctx->cmd_exec_on_index(conn, args); return dbctx->cmd_exec(conn, args);
} }
/* has modops */ /* has modops */
char *const mod_op_begin = start; char *const mod_op_begin = start;
...@@ -831,7 +888,8 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *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; char *const mod_op_end = start;
args.mod_op = string_ref(mod_op_begin, mod_op_end); args.mod_op = string_ref(mod_op_begin, mod_op_end);
const size_t num_uvals = args.pst->get_ret_fields().size(); 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) { for (size_t i = 0; i < num_uvals; ++i) {
skip_one(start, finish); skip_one(start, finish);
char *const f_begin = start; char *const f_begin = start;
...@@ -848,7 +906,7 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start, ...@@ -848,7 +906,7 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
} }
} }
args.uvals = uflds; args.uvals = uflds;
return dbctx->cmd_exec_on_index(conn, args); return dbctx->cmd_exec(conn, args);
} }
void void
...@@ -871,7 +929,7 @@ hstcpsvr_worker::do_authorization(char *start, char *finish, ...@@ -871,7 +929,7 @@ hstcpsvr_worker::do_authorization(char *start, char *finish,
char *wp = key_begin; char *wp = key_begin;
unescape_string(wp, key_begin, key_end); unescape_string(wp, key_begin, key_end);
if (authtype_len != 1 || authtype_begin[0] != '1') { 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 && if (cshared.plain_secret.size() == key_len &&
memcmp(cshared.plain_secret.data(), key_begin, key_len) == 0) { memcmp(cshared.plain_secret.data(), key_begin, key_len) == 0) {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define MYSQL_SERVER 1 #define MYSQL_SERVER 1
#include <my_config.h> #include <my_config.h>
#include <mysql_version.h> #include <mysql_version.h>
#if MYSQL_VERSION_ID >= 50505 #if MYSQL_VERSION_ID >= 50505
......
...@@ -33,5 +33,32 @@ typedef std::allocator<int> allocator_type; ...@@ -33,5 +33,32 @@ typedef std::allocator<int> allocator_type;
typedef std::allocator<int> allocator_type; typedef std::allocator<int> allocator_type;
#endif #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 #endif
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#include <string.h>
#include "util.hpp" #include "util.hpp"
namespace dena { namespace dena {
...@@ -33,7 +33,6 @@ struct auto_addrinfo : private noncopyable { ...@@ -33,7 +33,6 @@ struct auto_addrinfo : private noncopyable {
int family = AF_UNSPEC, int socktype = SOCK_STREAM, int protocol = 0) { int family = AF_UNSPEC, int socktype = SOCK_STREAM, int protocol = 0) {
reset(); reset();
addrinfo hints; addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = flags; hints.ai_flags = flags;
hints.ai_family = family; hints.ai_family = family;
hints.ai_socktype = socktype; hints.ai_socktype = socktype;
......
...@@ -106,8 +106,18 @@ read_ui32(char *& start, char *finish) ...@@ -106,8 +106,18 @@ read_ui32(char *& start, char *finish)
void void
write_ui32(string_buffer& buf, uint32_t v) write_ui32(string_buffer& buf, uint32_t v)
{ {
char *wp = buf.make_space(32); char *wp = buf.make_space(12);
int len = snprintf(wp, 32, "%u", v); 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) { if (len > 0) {
buf.space_wrote(len); buf.space_wrote(len);
} }
......
...@@ -25,6 +25,7 @@ bool unescape_string(string_buffer& ar, const char *start, const char *finish); ...@@ -25,6 +25,7 @@ bool unescape_string(string_buffer& ar, const char *start, const char *finish);
uint32_t read_ui32(char *& start, char *finish); uint32_t read_ui32(char *& start, char *finish);
void write_ui32(string_buffer& buf, uint32_t v); void write_ui32(string_buffer& buf, uint32_t v);
void write_ui64(string_buffer& buf, uint64_t v);
inline bool inline bool
is_null_expression(const char *start, const char *finish) is_null_expression(const char *start, const char *finish)
......
...@@ -31,21 +31,12 @@ struct hstcpcli : public hstcpcli_i, private noncopyable { ...@@ -31,21 +31,12 @@ struct hstcpcli : public hstcpcli_i, private noncopyable {
virtual bool stable_point(); virtual bool stable_point();
virtual void request_buf_open_index(size_t pst_id, const char *dbn, 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); const char *tbl, const char *idx, const char *retflds, const char *filflds);
#if 0 virtual void request_buf_auth(const char *secret, const char *typ);
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_exec_generic(size_t pst_id, const string_ref& op, 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 *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen, 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 request_send();
virtual int response_recv(size_t& num_flds_r); virtual int response_recv(size_t& num_flds_r);
virtual const string_ref *get_next_row(); virtual const string_ref *get_next_row();
...@@ -196,6 +187,27 @@ hstcpcli::request_buf_open_index(size_t pst_id, const char *dbn, ...@@ -196,6 +187,27 @@ hstcpcli::request_buf_open_index(size_t pst_id, const char *dbn,
++num_req_bufd; ++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 { namespace {
void void
...@@ -218,7 +230,8 @@ void ...@@ -218,7 +230,8 @@ void
hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op, 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 *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen, 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) { if (num_req_sent > 0 || num_req_rcvd > 0) {
close(); close();
...@@ -234,13 +247,26 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op, ...@@ -234,13 +247,26 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
const string_ref& kv = kvs[i]; const string_ref& kv = kvs[i];
append_delim_value(writebuf, kv.begin(), kv.end()); 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"); writebuf.append_literal("\t");
append_uint32(writebuf, limit); // FIXME size_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"); writebuf.append_literal("\t");
append_uint32(writebuf, skip); // FIXME size_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) { for (size_t i = 0; i < filslen; ++i) {
const hstcpcli_filter& f = fils[i]; const hstcpcli_filter& f = fils[i];
writebuf.append_literal("\t"); writebuf.append_literal("\t");
...@@ -264,44 +290,6 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op, ...@@ -264,44 +290,6 @@ hstcpcli::request_buf_exec_generic(size_t pst_id, const string_ref& op,
++num_req_bufd; ++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 int
hstcpcli::request_send() hstcpcli::request_send()
{ {
......
...@@ -37,13 +37,16 @@ struct hstcpcli_i { ...@@ -37,13 +37,16 @@ struct hstcpcli_i {
virtual void close() = 0; virtual void close() = 0;
virtual int reconnect() = 0; virtual int reconnect() = 0;
virtual bool stable_point() = 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, virtual void request_buf_open_index(size_t pst_id, const char *dbn,
const char *tbl, const char *idx, const char *retflds, const char *tbl, const char *idx, const char *retflds,
const char *filflds = 0) = 0; const char *filflds = 0) = 0;
virtual void request_buf_exec_generic(size_t pst_id, const string_ref& op, 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 *kvs, size_t kvslen, uint32_t limit, uint32_t skip,
const string_ref& mod_op, const string_ref *mvs, size_t mvslen, 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 request_send() = 0;
virtual int response_recv(size_t& num_flds_r) = 0; virtual int response_recv(size_t& num_flds_r) = 0;
virtual const string_ref *get_next_row() = 0; virtual const string_ref *get_next_row() = 0;
......
...@@ -84,7 +84,7 @@ struct string_buffer : private noncopyable { ...@@ -84,7 +84,7 @@ struct string_buffer : private noncopyable {
} }
void space_wrote(size_t len) { void space_wrote(size_t len) {
len = std::min(len, alloc_size - end_offset); len = std::min(len, alloc_size - end_offset);
end_offset = std::min(end_offset + len, alloc_size); end_offset += len;
} }
template <size_t N> template <size_t N>
void append_literal(const char (& str)[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) ...@@ -109,7 +109,7 @@ hv_to_strmap(HV *hv, std::map<std::string, std::string>& m_r)
static void static void
strrefarr_push_back(std::vector<dena::string_ref>& a_r, SV *sv) 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")); DBG(fprintf(stderr, "strrefarr_push_back: null\n"));
return a_r.push_back(dena::string_ref()); return a_r.push_back(dena::string_ref());
} }
...@@ -135,7 +135,7 @@ av_to_strrefarr(AV *av, std::vector<dena::string_ref>& a_r) ...@@ -135,7 +135,7 @@ av_to_strrefarr(AV *av, std::vector<dena::string_ref>& a_r)
static dena::string_ref static dena::string_ref
sv_get_string_ref(SV *sv) sv_get_string_ref(SV *sv)
{ {
if (sv == 0) { if (sv == 0 || SvTYPE(sv) == SVt_NULL) { /* !SvPOK()? */
return dena::string_ref(); return dena::string_ref();
} }
STRLEN vlen = 0; STRLEN vlen = 0;
...@@ -190,7 +190,8 @@ set_process_verbose_level(const std::map<std::string, std::string>& m) ...@@ -190,7 +190,8 @@ set_process_verbose_level(const std::map<std::string, std::string>& m)
static AV * static AV *
execute_internal(SV *obj, int id, const char *op, AV *keys, int limit, 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; AV *retval = (AV *)&PL_sv_undef;
dena::hstcpcli_i *const ptr = dena::hstcpcli_i *const ptr =
...@@ -198,6 +199,7 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit, ...@@ -198,6 +199,7 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
do { do {
std::vector<dena::string_ref> keyarr, mvarr; std::vector<dena::string_ref> keyarr, mvarr;
std::vector<dena::hstcpcli_filter> farr; std::vector<dena::hstcpcli_filter> farr;
std::vector<dena::string_ref> ivs;
av_to_strrefarr(keys, keyarr); av_to_strrefarr(keys, keyarr);
dena::string_ref modop_ref; dena::string_ref modop_ref;
if (modop != 0) { if (modop != 0) {
...@@ -207,9 +209,13 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit, ...@@ -207,9 +209,13 @@ execute_internal(SV *obj, int id, const char *op, AV *keys, int limit,
if (filters != 0) { if (filters != 0) {
av_to_filters(filters, farr); 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)), ptr->request_buf_exec_generic(id, dena::string_ref(op, strlen(op)),
&keyarr[0], keyarr.size(), limit, skip, modop_ref, &mvarr[0], &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(); AV *const av = newAV();
retval = av; retval = av;
if (ptr->request_send() != 0) { if (ptr->request_send() != 0) {
...@@ -258,8 +264,10 @@ struct execute_arg { ...@@ -258,8 +264,10 @@ struct execute_arg {
const char *modop; const char *modop;
AV *modvals; AV *modvals;
AV *filters; AV *filters;
int invalues_keypart;
AV *invalues;
execute_arg() : id(0), op(0), keys(0), limit(0), skip(0), modop(0), 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 * static AV *
...@@ -271,6 +279,7 @@ execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args) ...@@ -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) { for (size_t i = 0; i < num_args; ++i) {
std::vector<dena::string_ref> keyarr, mvarr; std::vector<dena::string_ref> keyarr, mvarr;
std::vector<dena::hstcpcli_filter> farr; std::vector<dena::hstcpcli_filter> farr;
std::vector<dena::string_ref> ivs;
const execute_arg& arg = args[i]; const execute_arg& arg = args[i];
av_to_strrefarr(arg.keys, keyarr); av_to_strrefarr(arg.keys, keyarr);
dena::string_ref modop_ref; dena::string_ref modop_ref;
...@@ -281,10 +290,13 @@ execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args) ...@@ -281,10 +290,13 @@ execute_multi_internal(SV *obj, const execute_arg *args, size_t num_args)
if (arg.filters != 0) { if (arg.filters != 0) {
av_to_filters(arg.filters, farr); 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, ptr->request_buf_exec_generic(arg.id,
dena::string_ref(arg.op, strlen(arg.op)), &keyarr[0], keyarr.size(), dena::string_ref(arg.op, strlen(arg.op)), &keyarr[0], keyarr.size(),
arg.limit, arg.skip, modop_ref, &mvarr[0], mvarr.size(), &farr[0], 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(); AV *const retval = newAV();
/* sends the requests */ /* sends the requests */
...@@ -419,6 +431,34 @@ CODE: ...@@ -419,6 +431,34 @@ CODE:
OUTPUT: OUTPUT:
RETVAL 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 int
open_index(obj, id, db, table, index, fields, ffields = 0) open_index(obj, id, db, table, index, fields, ffields = 0)
SV *obj SV *obj
...@@ -452,7 +492,7 @@ OUTPUT: ...@@ -452,7 +492,7 @@ OUTPUT:
RETVAL RETVAL
AV * 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 SV *obj
int id int id
const char *op const char *op
...@@ -462,12 +502,15 @@ execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0) ...@@ -462,12 +502,15 @@ execute_single(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
SV *mop SV *mop
SV *mvs SV *mvs
SV *fils SV *fils
int ivkeypart
SV *ivs
CODE: CODE:
const char *const mop_str = sv_get_strval(mop); const char *const mop_str = sv_get_strval(mop);
AV *const mvs_av = sv_get_arrval(mvs); AV *const mvs_av = sv_get_arrval(mvs);
AV *const fils_av = sv_get_arrval(fils); 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, RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
fils_av); fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL); sv_2mortal((SV *)RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
...@@ -500,9 +543,11 @@ CODE: ...@@ -500,9 +543,11 @@ CODE:
ag.modop = arr_get_strval(avtarget, argmax, 5); ag.modop = arr_get_strval(avtarget, argmax, 5);
ag.modvals = arr_get_arrval(avtarget, argmax, 6); ag.modvals = arr_get_arrval(avtarget, argmax, 6);
ag.filters = arr_get_arrval(avtarget, argmax, 7); 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, 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); RETVAL = execute_multi_internal(obj, args, cmdsmax + 1);
sv_2mortal((SV *)RETVAL); sv_2mortal((SV *)RETVAL);
...@@ -510,7 +555,7 @@ OUTPUT: ...@@ -510,7 +555,7 @@ OUTPUT:
RETVAL RETVAL
AV * 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 SV *obj
int id int id
const char *op const char *op
...@@ -520,18 +565,21 @@ execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0) ...@@ -520,18 +565,21 @@ execute_find(obj, id, op, keys, limit, skip, mop = 0, mvs = 0, fils = 0)
SV *mop SV *mop
SV *mvs SV *mvs
SV *fils SV *fils
int ivkeypart
SV *ivs
CODE: CODE:
const char *const mop_str = sv_get_strval(mop); const char *const mop_str = sv_get_strval(mop);
AV *const mvs_av = sv_get_arrval(mvs); AV *const mvs_av = sv_get_arrval(mvs);
AV *const fils_av = sv_get_arrval(fils); 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, RETVAL = execute_internal(obj, id, op, keys, limit, skip, mop_str, mvs_av,
fils_av); fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL); sv_2mortal((SV *)RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
AV * 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 SV *obj
int id int id
const char *op const char *op
...@@ -540,16 +588,19 @@ execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0) ...@@ -540,16 +588,19 @@ execute_update(obj, id, op, keys, limit, skip, modvals, fils = 0)
int skip int skip
AV *modvals AV *modvals
SV *fils SV *fils
int ivkeypart
SV *ivs
CODE: CODE:
AV *const fils_av = sv_get_arrval(fils); 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", RETVAL = execute_internal(obj, id, op, keys, limit, skip, "U",
modvals, fils_av); modvals, fils_av, ivkeypart, ivs_av);
sv_2mortal((SV *)RETVAL); sv_2mortal((SV *)RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
AV * 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 SV *obj
int id int id
const char *op const char *op
...@@ -557,9 +608,13 @@ execute_delete(obj, id, op, keys, limit, skip, fils = 0) ...@@ -557,9 +608,13 @@ execute_delete(obj, id, op, keys, limit, skip, fils = 0)
int limit int limit
int skip int skip
SV *fils SV *fils
int ivkeypart
SV *ivs
CODE: CODE:
AV *const fils_av = sv_get_arrval(fils); 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); sv_2mortal((SV *)RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
...@@ -570,7 +625,7 @@ execute_insert(obj, id, fvals) ...@@ -570,7 +625,7 @@ execute_insert(obj, id, fvals)
int id int id
AV *fvals AV *fvals
CODE: 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); sv_2mortal((SV *)RETVAL);
OUTPUT: OUTPUT:
RETVAL RETVAL
......
...@@ -5,4 +5,4 @@ MANIFEST ...@@ -5,4 +5,4 @@ MANIFEST
ppport.h ppport.h
README README
t/HandlerSocket.t t/HandlerSocket.t
lib/HandlerSocket.pm lib/Net/HandlerSocket.pm
...@@ -21,6 +21,7 @@ sub init_conf { ...@@ -21,6 +21,7 @@ sub init_conf {
$conf{user} = get_conf_env("MYSQLUSER", "root"); $conf{user} = get_conf_env("MYSQLUSER", "root");
$conf{pass} = get_conf_env("MYSQLPASS", ""); $conf{pass} = get_conf_env("MYSQLPASS", "");
$conf{hsport} = get_conf_env("HSPORT", 9998); $conf{hsport} = get_conf_env("HSPORT", 9998);
$conf{hspass} = get_conf_env("HSPASS", undef);
} }
sub get_dbi_connection { sub get_dbi_connection {
...@@ -52,6 +53,9 @@ sub get_hs_connection { ...@@ -52,6 +53,9 @@ sub get_hs_connection {
$port ||= $conf{hsport}; $port ||= $conf{hsport};
my $hsargs = { 'host' => $host, 'port' => $port }; my $hsargs = { 'host' => $host, 'port' => $port };
my $conn = new Net::HandlerSocket($hsargs); my $conn = new Net::HandlerSocket($hsargs);
if (defined($conn) && defined($conf{hspass})) {
$conn->auth($conf{hspass});
}
return $conn; return $conn;
} }
......
#!/bin/bash #!/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 source ../common/compat.sh
......
HSINSERT 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 DUMP_TABLE
1 v1sql_0 v2sql_0 1 v1sql_0 v2sql_0
2 v1sql_1 v2sql_1 2 v1sql_1 v2sql_1
......
...@@ -47,6 +47,9 @@ for (my $i = 0; $i < $tablesize; ++$i) { ...@@ -47,6 +47,9 @@ for (my $i = 0; $i < $tablesize; ++$i) {
if ($err != 0) { if ($err != 0) {
my $err_str = $r->[1]; my $err_str = $r->[1];
print "$err $err_str\n"; 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 # make sure that it works even when inserts are pipelined. these requests
...@@ -63,8 +66,11 @@ for (my $i = 0; $i < $tablesize; ++$i) { ...@@ -63,8 +66,11 @@ for (my $i = 0; $i < $tablesize; ++$i) {
for (my $i = 0; $i < 3; ++$i) { for (my $i = 0; $i < 3; ++$i) {
my $err = $r->[$i]->[0]; my $err = $r->[$i]->[0];
if ($err != 0) { if ($err != 0) {
my $err_str = $r->[1]; my $err_str = $r->[$i]->[1];
print "$err $err_str\n"; 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);
}
}
TYPE TINYINT
DUMP_TABLE_BEGIN
-128 s-128 -128
-42 s-42 -42
-14 s-14 -14
-4 s-4 -4
-1 s-1 -1
0 s0 0
1 s1 1
4 s4 4
14 s14 14
42 s42 42
127 s127 127
DUMP_TABLE_END
PK[-128] -128 s-128 -128
I1[s-128] -128 s-128 -128
I2[-128, s-128] -128 s-128 -128
I2p[-128] -128 s-128 -128
PK[-42] -42 s-42 -42
I1[s-42] -42 s-42 -42
I2[-42, s-42] -42 s-42 -42
I2p[-42] -42 s-42 -42
PK[-14] -14 s-14 -14
I1[s-14] -14 s-14 -14
I2[-14, s-14] -14 s-14 -14
I2p[-14] -14 s-14 -14
PK[-4] -4 s-4 -4
I1[s-4] -4 s-4 -4
I2[-4, s-4] -4 s-4 -4
I2p[-4] -4 s-4 -4
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[4] 4 s4 4
I1[s4] 4 s4 4
I2[4, s4] 4 s4 4
I2p[4] 4 s4 4
PK[14] 14 s14 14
I1[s14] 14 s14 14
I2[14, s14] 14 s14 14
I2p[14] 14 s14 14
PK[42] 42 s42 42
I1[s42] 42 s42 42
I2[42, s42] 42 s42 42
I2p[42] 42 s42 42
PK[127] 127 s127 127
I1[s127] 127 s127 127
I2[127, s127] 127 s127 127
I2p[127] 127 s127 127
TYPE TINYINT UNSIGNED
DUMP_TABLE_BEGIN
0 s0 0
1 s1 1
3 s3 3
9 s9 9
28 s28 28
85 s85 85
255 s255 255
DUMP_TABLE_END
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[3] 3 s3 3
I1[s3] 3 s3 3
I2[3, s3] 3 s3 3
I2p[3] 3 s3 3
PK[9] 9 s9 9
I1[s9] 9 s9 9
I2[9, s9] 9 s9 9
I2p[9] 9 s9 9
PK[28] 28 s28 28
I1[s28] 28 s28 28
I2[28, s28] 28 s28 28
I2p[28] 28 s28 28
PK[85] 85 s85 85
I1[s85] 85 s85 85
I2[85, s85] 85 s85 85
I2p[85] 85 s85 85
PK[255] 255 s255 255
I1[s255] 255 s255 255
I2[255, s255] 255 s255 255
I2p[255] 255 s255 255
TYPE SMALLINT
DUMP_TABLE_BEGIN
-32768 s-32768 -32768
-10922 s-10922 -10922
-3640 s-3640 -3640
-1213 s-1213 -1213
-404 s-404 -404
-134 s-134 -134
-1 s-1 -1
0 s0 0
1 s1 1
134 s134 134
404 s404 404
1213 s1213 1213
3640 s3640 3640
10922 s10922 10922
32767 s32768 32767
DUMP_TABLE_END
PK[-32768] -32768 s-32768 -32768
I1[s-32768] -32768 s-32768 -32768
I2[-32768, s-32768] -32768 s-32768 -32768
I2p[-32768] -32768 s-32768 -32768
PK[-10922] -10922 s-10922 -10922
I1[s-10922] -10922 s-10922 -10922
I2[-10922, s-10922] -10922 s-10922 -10922
I2p[-10922] -10922 s-10922 -10922
PK[-3640] -3640 s-3640 -3640
I1[s-3640] -3640 s-3640 -3640
I2[-3640, s-3640] -3640 s-3640 -3640
I2p[-3640] -3640 s-3640 -3640
PK[-1213] -1213 s-1213 -1213
I1[s-1213] -1213 s-1213 -1213
I2[-1213, s-1213] -1213 s-1213 -1213
I2p[-1213] -1213 s-1213 -1213
PK[-404] -404 s-404 -404
I1[s-404] -404 s-404 -404
I2[-404, s-404] -404 s-404 -404
I2p[-404] -404 s-404 -404
PK[-134] -134 s-134 -134
I1[s-134] -134 s-134 -134
I2[-134, s-134] -134 s-134 -134
I2p[-134] -134 s-134 -134
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[134] 134 s134 134
I1[s134] 134 s134 134
I2[134, s134] 134 s134 134
I2p[134] 134 s134 134
PK[404] 404 s404 404
I1[s404] 404 s404 404
I2[404, s404] 404 s404 404
I2p[404] 404 s404 404
PK[1213] 1213 s1213 1213
I1[s1213] 1213 s1213 1213
I2[1213, s1213] 1213 s1213 1213
I2p[1213] 1213 s1213 1213
PK[3640] 3640 s3640 3640
I1[s3640] 3640 s3640 3640
I2[3640, s3640] 3640 s3640 3640
I2p[3640] 3640 s3640 3640
PK[10922] 10922 s10922 10922
I1[s10922] 10922 s10922 10922
I2[10922, s10922] 10922 s10922 10922
I2p[10922] 10922 s10922 10922
PK[32768] 32767 s32768 32767
I1[s32768] 32767 s32768 32767
I2[32768, s32768] 32767 s32768 32767
I2p[32768] 32767 s32768 32767
TYPE SMALLINT UNSIGNED
DUMP_TABLE_BEGIN
0 s0 0
1 s1 1
269 s269 269
809 s809 809
2427 s2427 2427
7281 s7281 7281
21845 s21845 21845
65535 s65535 65535
DUMP_TABLE_END
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[269] 269 s269 269
I1[s269] 269 s269 269
I2[269, s269] 269 s269 269
I2p[269] 269 s269 269
PK[809] 809 s809 809
I1[s809] 809 s809 809
I2[809, s809] 809 s809 809
I2p[809] 809 s809 809
PK[2427] 2427 s2427 2427
I1[s2427] 2427 s2427 2427
I2[2427, s2427] 2427 s2427 2427
I2p[2427] 2427 s2427 2427
PK[7281] 7281 s7281 7281
I1[s7281] 7281 s7281 7281
I2[7281, s7281] 7281 s7281 7281
I2p[7281] 7281 s7281 7281
PK[21845] 21845 s21845 21845
I1[s21845] 21845 s21845 21845
I2[21845, s21845] 21845 s21845 21845
I2p[21845] 21845 s21845 21845
PK[65535] 65535 s65535 65535
I1[s65535] 65535 s65535 65535
I2[65535, s65535] 65535 s65535 65535
I2p[65535] 65535 s65535 65535
TYPE MEDIUMINT
DUMP_TABLE_BEGIN
-8388608 s-8388608 -8388608
-2796202 s-2796202 -2796202
-932067 s-932067 -932067
-310689 s-310689 -310689
-103563 s-103563 -103563
-34521 s-34521 -34521
-1 s-1 -1
0 s0 0
1 s1 1
34521 s34521 34521
103563 s103563 103563
310689 s310689 310689
932067 s932067 932067
2796202 s2796202 2796202
8388607 s8388607 8388607
DUMP_TABLE_END
PK[-8388608] -8388608 s-8388608 -8388608
I1[s-8388608] -8388608 s-8388608 -8388608
I2[-8388608, s-8388608] -8388608 s-8388608 -8388608
I2p[-8388608] -8388608 s-8388608 -8388608
PK[-2796202] -2796202 s-2796202 -2796202
I1[s-2796202] -2796202 s-2796202 -2796202
I2[-2796202, s-2796202] -2796202 s-2796202 -2796202
I2p[-2796202] -2796202 s-2796202 -2796202
PK[-932067] -932067 s-932067 -932067
I1[s-932067] -932067 s-932067 -932067
I2[-932067, s-932067] -932067 s-932067 -932067
I2p[-932067] -932067 s-932067 -932067
PK[-310689] -310689 s-310689 -310689
I1[s-310689] -310689 s-310689 -310689
I2[-310689, s-310689] -310689 s-310689 -310689
I2p[-310689] -310689 s-310689 -310689
PK[-103563] -103563 s-103563 -103563
I1[s-103563] -103563 s-103563 -103563
I2[-103563, s-103563] -103563 s-103563 -103563
I2p[-103563] -103563 s-103563 -103563
PK[-34521] -34521 s-34521 -34521
I1[s-34521] -34521 s-34521 -34521
I2[-34521, s-34521] -34521 s-34521 -34521
I2p[-34521] -34521 s-34521 -34521
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[34521] 34521 s34521 34521
I1[s34521] 34521 s34521 34521
I2[34521, s34521] 34521 s34521 34521
I2p[34521] 34521 s34521 34521
PK[103563] 103563 s103563 103563
I1[s103563] 103563 s103563 103563
I2[103563, s103563] 103563 s103563 103563
I2p[103563] 103563 s103563 103563
PK[310689] 310689 s310689 310689
I1[s310689] 310689 s310689 310689
I2[310689, s310689] 310689 s310689 310689
I2p[310689] 310689 s310689 310689
PK[932067] 932067 s932067 932067
I1[s932067] 932067 s932067 932067
I2[932067, s932067] 932067 s932067 932067
I2p[932067] 932067 s932067 932067
PK[2796202] 2796202 s2796202 2796202
I1[s2796202] 2796202 s2796202 2796202
I2[2796202, s2796202] 2796202 s2796202 2796202
I2p[2796202] 2796202 s2796202 2796202
PK[8388607] 8388607 s8388607 8388607
I1[s8388607] 8388607 s8388607 8388607
I2[8388607, s8388607] 8388607 s8388607 8388607
I2p[8388607] 8388607 s8388607 8388607
TYPE MEDIUMINT UNSIGNED
DUMP_TABLE_BEGIN
0 s0 0
1 s1 1
69042 s69042 69042
207126 s207126 207126
621378 s621378 621378
1864135 s1864135 1864135
5592405 s5592405 5592405
16777215 s16777215 16777215
DUMP_TABLE_END
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[69042] 69042 s69042 69042
I1[s69042] 69042 s69042 69042
I2[69042, s69042] 69042 s69042 69042
I2p[69042] 69042 s69042 69042
PK[207126] 207126 s207126 207126
I1[s207126] 207126 s207126 207126
I2[207126, s207126] 207126 s207126 207126
I2p[207126] 207126 s207126 207126
PK[621378] 621378 s621378 621378
I1[s621378] 621378 s621378 621378
I2[621378, s621378] 621378 s621378 621378
I2p[621378] 621378 s621378 621378
PK[1864135] 1864135 s1864135 1864135
I1[s1864135] 1864135 s1864135 1864135
I2[1864135, s1864135] 1864135 s1864135 1864135
I2p[1864135] 1864135 s1864135 1864135
PK[5592405] 5592405 s5592405 5592405
I1[s5592405] 5592405 s5592405 5592405
I2[5592405, s5592405] 5592405 s5592405 5592405
I2p[5592405] 5592405 s5592405 5592405
PK[16777215] 16777215 s16777215 16777215
I1[s16777215] 16777215 s16777215 16777215
I2[16777215, s16777215] 16777215 s16777215 16777215
I2p[16777215] 16777215 s16777215 16777215
TYPE INT
DUMP_TABLE_BEGIN
-2147483648 s-2147483648 -2147483648
-715827882 s-715827882 -715827882
-238609294 s-238609294 -238609294
-79536431 s-79536431 -79536431
-26512143 s-26512143 -26512143
-8837381 s-8837381 -8837381
-1 s-1 -1
0 s0 0
1 s1 1
8837381 s8837381 8837381
26512143 s26512143 26512143
79536431 s79536431 79536431
238609294 s238609294 238609294
715827882 s715827882 715827882
2147483647 s2147483647 2147483647
DUMP_TABLE_END
PK[-2147483648] -2147483648 s-2147483648 -2147483648
I1[s-2147483648] -2147483648 s-2147483648 -2147483648
I2[-2147483648, s-2147483648] -2147483648 s-2147483648 -2147483648
I2p[-2147483648] -2147483648 s-2147483648 -2147483648
PK[-715827882] -715827882 s-715827882 -715827882
I1[s-715827882] -715827882 s-715827882 -715827882
I2[-715827882, s-715827882] -715827882 s-715827882 -715827882
I2p[-715827882] -715827882 s-715827882 -715827882
PK[-238609294] -238609294 s-238609294 -238609294
I1[s-238609294] -238609294 s-238609294 -238609294
I2[-238609294, s-238609294] -238609294 s-238609294 -238609294
I2p[-238609294] -238609294 s-238609294 -238609294
PK[-79536431] -79536431 s-79536431 -79536431
I1[s-79536431] -79536431 s-79536431 -79536431
I2[-79536431, s-79536431] -79536431 s-79536431 -79536431
I2p[-79536431] -79536431 s-79536431 -79536431
PK[-26512143] -26512143 s-26512143 -26512143
I1[s-26512143] -26512143 s-26512143 -26512143
I2[-26512143, s-26512143] -26512143 s-26512143 -26512143
I2p[-26512143] -26512143 s-26512143 -26512143
PK[-8837381] -8837381 s-8837381 -8837381
I1[s-8837381] -8837381 s-8837381 -8837381
I2[-8837381, s-8837381] -8837381 s-8837381 -8837381
I2p[-8837381] -8837381 s-8837381 -8837381
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[8837381] 8837381 s8837381 8837381
I1[s8837381] 8837381 s8837381 8837381
I2[8837381, s8837381] 8837381 s8837381 8837381
I2p[8837381] 8837381 s8837381 8837381
PK[26512143] 26512143 s26512143 26512143
I1[s26512143] 26512143 s26512143 26512143
I2[26512143, s26512143] 26512143 s26512143 26512143
I2p[26512143] 26512143 s26512143 26512143
PK[79536431] 79536431 s79536431 79536431
I1[s79536431] 79536431 s79536431 79536431
I2[79536431, s79536431] 79536431 s79536431 79536431
I2p[79536431] 79536431 s79536431 79536431
PK[238609294] 238609294 s238609294 238609294
I1[s238609294] 238609294 s238609294 238609294
I2[238609294, s238609294] 238609294 s238609294 238609294
I2p[238609294] 238609294 s238609294 238609294
PK[715827882] 715827882 s715827882 715827882
I1[s715827882] 715827882 s715827882 715827882
I2[715827882, s715827882] 715827882 s715827882 715827882
I2p[715827882] 715827882 s715827882 715827882
PK[2147483647] 2147483647 s2147483647 2147483647
I1[s2147483647] 2147483647 s2147483647 2147483647
I2[2147483647, s2147483647] 2147483647 s2147483647 2147483647
I2p[2147483647] 2147483647 s2147483647 2147483647
TYPE INT UNSIGNED
DUMP_TABLE_BEGIN
0 s0 0
1 s1 1
17674762 s17674762 17674762
53024287 s53024287 53024287
159072862 s159072862 159072862
477218588 s477218588 477218588
1431655765 s1431655765 1431655765
4294967295 s4294967295 4294967295
DUMP_TABLE_END
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[17674762] 17674762 s17674762 17674762
I1[s17674762] 17674762 s17674762 17674762
I2[17674762, s17674762] 17674762 s17674762 17674762
I2p[17674762] 17674762 s17674762 17674762
PK[53024287] 53024287 s53024287 53024287
I1[s53024287] 53024287 s53024287 53024287
I2[53024287, s53024287] 53024287 s53024287 53024287
I2p[53024287] 53024287 s53024287 53024287
PK[159072862] 159072862 s159072862 159072862
I1[s159072862] 159072862 s159072862 159072862
I2[159072862, s159072862] 159072862 s159072862 159072862
I2p[159072862] 159072862 s159072862 159072862
PK[477218588] 477218588 s477218588 477218588
I1[s477218588] 477218588 s477218588 477218588
I2[477218588, s477218588] 477218588 s477218588 477218588
I2p[477218588] 477218588 s477218588 477218588
PK[1431655765] 1431655765 s1431655765 1431655765
I1[s1431655765] 1431655765 s1431655765 1431655765
I2[1431655765, s1431655765] 1431655765 s1431655765 1431655765
I2p[1431655765] 1431655765 s1431655765 1431655765
PK[4294967295] 4294967295 s4294967295 4294967295
I1[s4294967295] 4294967295 s4294967295 4294967295
I2[4294967295, s4294967295] 4294967295 s4294967295 4294967295
I2p[4294967295] 4294967295 s4294967295 4294967295
TYPE BIGINT
DUMP_TABLE_BEGIN
-9223372036854775808 s-9223372036854775808 -9223372036854775808
-3074457345618258602 s-3074457345618258602 -3074457345618258602
-1024819115206086200 s-1024819115206086200 -1024819115206086200
-341606371735362066 s-341606371735362066 -341606371735362066
-113868790578454022 s-113868790578454022 -113868790578454022
-37956263526151340 s-37956263526151340 -37956263526151340
-1 s-1 -1
0 s0 0
1 s1 1
37956263526151340 s37956263526151340 37956263526151340
113868790578454022 s113868790578454022 113868790578454022
341606371735362066 s341606371735362066 341606371735362066
1024819115206086200 s1024819115206086200 1024819115206086200
3074457345618258602 s3074457345618258602 3074457345618258602
9223372036854775807 s9223372036854775807 9223372036854775807
DUMP_TABLE_END
PK[-9223372036854775808] -9223372036854775808 s-9223372036854775808 -9223372036854775808
I1[s-9223372036854775808] -9223372036854775808 s-9223372036854775808 -9223372036854775808
I2[-9223372036854775808, s-9223372036854775808] -9223372036854775808 s-9223372036854775808 -9223372036854775808
I2p[-9223372036854775808] -9223372036854775808 s-9223372036854775808 -9223372036854775808
PK[-3074457345618258602] -3074457345618258602 s-3074457345618258602 -3074457345618258602
I1[s-3074457345618258602] -3074457345618258602 s-3074457345618258602 -3074457345618258602
I2[-3074457345618258602, s-3074457345618258602] -3074457345618258602 s-3074457345618258602 -3074457345618258602
I2p[-3074457345618258602] -3074457345618258602 s-3074457345618258602 -3074457345618258602
PK[-1024819115206086200] -1024819115206086200 s-1024819115206086200 -1024819115206086200
I1[s-1024819115206086200] -1024819115206086200 s-1024819115206086200 -1024819115206086200
I2[-1024819115206086200, s-1024819115206086200] -1024819115206086200 s-1024819115206086200 -1024819115206086200
I2p[-1024819115206086200] -1024819115206086200 s-1024819115206086200 -1024819115206086200
PK[-341606371735362066] -341606371735362066 s-341606371735362066 -341606371735362066
I1[s-341606371735362066] -341606371735362066 s-341606371735362066 -341606371735362066
I2[-341606371735362066, s-341606371735362066] -341606371735362066 s-341606371735362066 -341606371735362066
I2p[-341606371735362066] -341606371735362066 s-341606371735362066 -341606371735362066
PK[-113868790578454022] -113868790578454022 s-113868790578454022 -113868790578454022
I1[s-113868790578454022] -113868790578454022 s-113868790578454022 -113868790578454022
I2[-113868790578454022, s-113868790578454022] -113868790578454022 s-113868790578454022 -113868790578454022
I2p[-113868790578454022] -113868790578454022 s-113868790578454022 -113868790578454022
PK[-37956263526151340] -37956263526151340 s-37956263526151340 -37956263526151340
I1[s-37956263526151340] -37956263526151340 s-37956263526151340 -37956263526151340
I2[-37956263526151340, s-37956263526151340] -37956263526151340 s-37956263526151340 -37956263526151340
I2p[-37956263526151340] -37956263526151340 s-37956263526151340 -37956263526151340
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[37956263526151340] 37956263526151340 s37956263526151340 37956263526151340
I1[s37956263526151340] 37956263526151340 s37956263526151340 37956263526151340
I2[37956263526151340, s37956263526151340] 37956263526151340 s37956263526151340 37956263526151340
I2p[37956263526151340] 37956263526151340 s37956263526151340 37956263526151340
PK[113868790578454022] 113868790578454022 s113868790578454022 113868790578454022
I1[s113868790578454022] 113868790578454022 s113868790578454022 113868790578454022
I2[113868790578454022, s113868790578454022] 113868790578454022 s113868790578454022 113868790578454022
I2p[113868790578454022] 113868790578454022 s113868790578454022 113868790578454022
PK[341606371735362066] 341606371735362066 s341606371735362066 341606371735362066
I1[s341606371735362066] 341606371735362066 s341606371735362066 341606371735362066
I2[341606371735362066, s341606371735362066] 341606371735362066 s341606371735362066 341606371735362066
I2p[341606371735362066] 341606371735362066 s341606371735362066 341606371735362066
PK[1024819115206086200] 1024819115206086200 s1024819115206086200 1024819115206086200
I1[s1024819115206086200] 1024819115206086200 s1024819115206086200 1024819115206086200
I2[1024819115206086200, s1024819115206086200] 1024819115206086200 s1024819115206086200 1024819115206086200
I2p[1024819115206086200] 1024819115206086200 s1024819115206086200 1024819115206086200
PK[3074457345618258602] 3074457345618258602 s3074457345618258602 3074457345618258602
I1[s3074457345618258602] 3074457345618258602 s3074457345618258602 3074457345618258602
I2[3074457345618258602, s3074457345618258602] 3074457345618258602 s3074457345618258602 3074457345618258602
I2p[3074457345618258602] 3074457345618258602 s3074457345618258602 3074457345618258602
PK[9223372036854775807] 9223372036854775807 s9223372036854775807 9223372036854775807
I1[s9223372036854775807] 9223372036854775807 s9223372036854775807 9223372036854775807
I2[9223372036854775807, s9223372036854775807] 9223372036854775807 s9223372036854775807 9223372036854775807
I2p[9223372036854775807] 9223372036854775807 s9223372036854775807 9223372036854775807
TYPE BIGINT UNSIGNED
DUMP_TABLE_BEGIN
0 s0 0
1 s1 1
75912527052302681 s75912527052302681 75912527052302681
227737581156908044 s227737581156908044 227737581156908044
683212743470724133 s683212743470724133 683212743470724133
2049638230412172401 s2049638230412172401 2049638230412172401
6148914691236517205 s6148914691236517205 6148914691236517205
18446744073709551615 s18446744073709551615 18446744073709551615
DUMP_TABLE_END
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[75912527052302681] 75912527052302681 s75912527052302681 75912527052302681
I1[s75912527052302681] 75912527052302681 s75912527052302681 75912527052302681
I2[75912527052302681, s75912527052302681] 75912527052302681 s75912527052302681 75912527052302681
I2p[75912527052302681] 75912527052302681 s75912527052302681 75912527052302681
PK[227737581156908044] 227737581156908044 s227737581156908044 227737581156908044
I1[s227737581156908044] 227737581156908044 s227737581156908044 227737581156908044
I2[227737581156908044, s227737581156908044] 227737581156908044 s227737581156908044 227737581156908044
I2p[227737581156908044] 227737581156908044 s227737581156908044 227737581156908044
PK[683212743470724133] 683212743470724133 s683212743470724133 683212743470724133
I1[s683212743470724133] 683212743470724133 s683212743470724133 683212743470724133
I2[683212743470724133, s683212743470724133] 683212743470724133 s683212743470724133 683212743470724133
I2p[683212743470724133] 683212743470724133 s683212743470724133 683212743470724133
PK[2049638230412172401] 2049638230412172401 s2049638230412172401 2049638230412172401
I1[s2049638230412172401] 2049638230412172401 s2049638230412172401 2049638230412172401
I2[2049638230412172401, s2049638230412172401] 2049638230412172401 s2049638230412172401 2049638230412172401
I2p[2049638230412172401] 2049638230412172401 s2049638230412172401 2049638230412172401
PK[6148914691236517205] 6148914691236517205 s6148914691236517205 6148914691236517205
I1[s6148914691236517205] 6148914691236517205 s6148914691236517205 6148914691236517205
I2[6148914691236517205, s6148914691236517205] 6148914691236517205 s6148914691236517205 6148914691236517205
I2p[6148914691236517205] 6148914691236517205 s6148914691236517205 6148914691236517205
PK[18446744073709551615] 18446744073709551615 s18446744073709551615 18446744073709551615
I1[s18446744073709551615] 18446744073709551615 s18446744073709551615 18446744073709551615
I2[18446744073709551615, s18446744073709551615] 18446744073709551615 s18446744073709551615 18446744073709551615
I2p[18446744073709551615] 18446744073709551615 s18446744073709551615 18446744073709551615
TYPE FLOAT
DUMP_TABLE_BEGIN
-32768 s-32768 -32768
-10922 s-10922 -10922
-3640 s-3640 -3640
-1213 s-1213 -1213
-404 s-404 -404
-134 s-134 -134
-1 s-1 -1
0 s0 0
1 s1 1
134 s134 134
404 s404 404
1213 s1213 1213
3640 s3640 3640
10922 s10922 10922
32768 s32768 32768
DUMP_TABLE_END
PK[-32768] -32768 s-32768 -32768
I1[s-32768] -32768 s-32768 -32768
I2[-32768, s-32768] -32768 s-32768 -32768
I2p[-32768] -32768 s-32768 -32768
PK[-10922] -10922 s-10922 -10922
I1[s-10922] -10922 s-10922 -10922
I2[-10922, s-10922] -10922 s-10922 -10922
I2p[-10922] -10922 s-10922 -10922
PK[-3640] -3640 s-3640 -3640
I1[s-3640] -3640 s-3640 -3640
I2[-3640, s-3640] -3640 s-3640 -3640
I2p[-3640] -3640 s-3640 -3640
PK[-1213] -1213 s-1213 -1213
I1[s-1213] -1213 s-1213 -1213
I2[-1213, s-1213] -1213 s-1213 -1213
I2p[-1213] -1213 s-1213 -1213
PK[-404] -404 s-404 -404
I1[s-404] -404 s-404 -404
I2[-404, s-404] -404 s-404 -404
I2p[-404] -404 s-404 -404
PK[-134] -134 s-134 -134
I1[s-134] -134 s-134 -134
I2[-134, s-134] -134 s-134 -134
I2p[-134] -134 s-134 -134
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[134] 134 s134 134
I1[s134] 134 s134 134
I2[134, s134] 134 s134 134
I2p[134] 134 s134 134
PK[404] 404 s404 404
I1[s404] 404 s404 404
I2[404, s404] 404 s404 404
I2p[404] 404 s404 404
PK[1213] 1213 s1213 1213
I1[s1213] 1213 s1213 1213
I2[1213, s1213] 1213 s1213 1213
I2p[1213] 1213 s1213 1213
PK[3640] 3640 s3640 3640
I1[s3640] 3640 s3640 3640
I2[3640, s3640] 3640 s3640 3640
I2p[3640] 3640 s3640 3640
PK[10922] 10922 s10922 10922
I1[s10922] 10922 s10922 10922
I2[10922, s10922] 10922 s10922 10922
I2p[10922] 10922 s10922 10922
PK[32768] 32768 s32768 32768
I1[s32768] 32768 s32768 32768
I2[32768, s32768] 32768 s32768 32768
I2p[32768] 32768 s32768 32768
TYPE DOUBLE
DUMP_TABLE_BEGIN
-2147483648 s-2147483648 -2147483648
-715827882 s-715827882 -715827882
-238609294 s-238609294 -238609294
-79536431 s-79536431 -79536431
-26512143 s-26512143 -26512143
-8837381 s-8837381 -8837381
-1 s-1 -1
0 s0 0
1 s1 1
8837381 s8837381 8837381
26512143 s26512143 26512143
79536431 s79536431 79536431
238609294 s238609294 238609294
715827882 s715827882 715827882
2147483647 s2147483647 2147483647
DUMP_TABLE_END
PK[-2147483648] -2147483648 s-2147483648 -2147483648
I1[s-2147483648] -2147483648 s-2147483648 -2147483648
I2[-2147483648, s-2147483648] -2147483648 s-2147483648 -2147483648
I2p[-2147483648] -2147483648 s-2147483648 -2147483648
PK[-715827882] -715827882 s-715827882 -715827882
I1[s-715827882] -715827882 s-715827882 -715827882
I2[-715827882, s-715827882] -715827882 s-715827882 -715827882
I2p[-715827882] -715827882 s-715827882 -715827882
PK[-238609294] -238609294 s-238609294 -238609294
I1[s-238609294] -238609294 s-238609294 -238609294
I2[-238609294, s-238609294] -238609294 s-238609294 -238609294
I2p[-238609294] -238609294 s-238609294 -238609294
PK[-79536431] -79536431 s-79536431 -79536431
I1[s-79536431] -79536431 s-79536431 -79536431
I2[-79536431, s-79536431] -79536431 s-79536431 -79536431
I2p[-79536431] -79536431 s-79536431 -79536431
PK[-26512143] -26512143 s-26512143 -26512143
I1[s-26512143] -26512143 s-26512143 -26512143
I2[-26512143, s-26512143] -26512143 s-26512143 -26512143
I2p[-26512143] -26512143 s-26512143 -26512143
PK[-8837381] -8837381 s-8837381 -8837381
I1[s-8837381] -8837381 s-8837381 -8837381
I2[-8837381, s-8837381] -8837381 s-8837381 -8837381
I2p[-8837381] -8837381 s-8837381 -8837381
PK[-1] -1 s-1 -1
I1[s-1] -1 s-1 -1
I2[-1, s-1] -1 s-1 -1
I2p[-1] -1 s-1 -1
PK[0] 0 s0 0
I1[s0] 0 s0 0
I2[0, s0] 0 s0 0
I2p[0] 0 s0 0
PK[1] 1 s1 1
I1[s1] 1 s1 1
I2[1, s1] 1 s1 1
I2p[1] 1 s1 1
PK[8837381] 8837381 s8837381 8837381
I1[s8837381] 8837381 s8837381 8837381
I2[8837381, s8837381] 8837381 s8837381 8837381
I2p[8837381] 8837381 s8837381 8837381
PK[26512143] 26512143 s26512143 26512143
I1[s26512143] 26512143 s26512143 26512143
I2[26512143, s26512143] 26512143 s26512143 26512143
I2p[26512143] 26512143 s26512143 26512143
PK[79536431] 79536431 s79536431 79536431
I1[s79536431] 79536431 s79536431 79536431
I2[79536431, s79536431] 79536431 s79536431 79536431
I2p[79536431] 79536431 s79536431 79536431
PK[238609294] 238609294 s238609294 238609294
I1[s238609294] 238609294 s238609294 238609294
I2[238609294, s238609294] 238609294 s238609294 238609294
I2p[238609294] 238609294 s238609294 238609294
PK[715827882] 715827882 s715827882 715827882
I1[s715827882] 715827882 s715827882 715827882
I2[715827882, s715827882] 715827882 s715827882 715827882
I2p[715827882] 715827882 s715827882 715827882
PK[2147483647] 2147483647 s2147483647 2147483647
I1[s2147483647] 2147483647 s2147483647 2147483647
I2[2147483647, s2147483647] 2147483647 s2147483647 2147483647
I2p[2147483647] 2147483647 s2147483647 2147483647
#!/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 source diff could not be displayed because it is too large. You can view the blob instead.
#!/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, ...@@ -2687,6 +2687,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
void handler::ha_release_auto_increment() void handler::ha_release_auto_increment()
{ {
DBUG_ENTER("ha_release_auto_increment");
release_auto_increment(); release_auto_increment();
insert_id_for_cur_row= 0; insert_id_for_cur_row= 0;
auto_inc_interval_for_cur_row.replace(0, 0, 0); auto_inc_interval_for_cur_row.replace(0, 0, 0);
...@@ -2700,6 +2701,7 @@ void handler::ha_release_auto_increment() ...@@ -2700,6 +2701,7 @@ void handler::ha_release_auto_increment()
*/ */
table->in_use->auto_inc_intervals_forced.empty(); 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