Commit 7202c21b authored by Michael Widenius's avatar Michael Widenius

Merge of patch lp:~ahiguti100/maria/handlersocket-fix-78 by Akira Higuchi

A bugfix of HandlerSocket is not applied to mariadb yet
parent 53d44ad1
......@@ -66,7 +66,7 @@ Here is a list of other language bindings:
https://github.com/koichik/node-handlersocket
The home of HandlerSocket is here:
https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL
More documents are available in docs-en/ and docs-ja/ directories.
......@@ -17,10 +17,11 @@ crash, etc).
$ ./autogen.sh
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
--with-mysql-source refers to the top of MySQL source directory,
--with-mysql-bindir refers to where MySQL binary executables (i.e.
mysql_config) are located, and --with-mysql-plugindir refers to a plugin
directory where plugin libraries (*.so) are installed.
--with-mysql-source refers to the top of MySQL source directory (which
contains the VERSION file or the configure.in file), --with-mysql-bindir
refers to where MySQL binary executables (i.e. mysql_config) are located,
and --with-mysql-plugindir refers to a plugin directory where plugin
libraries (*.so) are installed.
$ make
$ sudo make install
......
......@@ -93,7 +93,6 @@ The execute_single method can be used for inserting records also.
my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]);
die $hs->get_error() if $res->[0] != 0;
my $num_inserted_rows = $res->[1];
The 3rd argument must be an arrayref whose elements correspond to
the 5th argument for the corresponding open_index call. If there
......@@ -116,6 +115,15 @@ executing them separatedly.
# ...
}
-----------------------------------------------------------------
If handlersocket is configured to authenticate client connections
(ie., handlersocket_plain_secret or handlersocket_plain_secret_wr
is set), a client must call 'auth' method before any other
methods.
my $res = $hs->auth('password');
die $hs->get_error() if $res->[0] != 0;
-----------------------------------------------------------------
When an error is occured, the first element of the returned
arrayref becomes a non-zero value. A negative value indicates
......
......@@ -29,7 +29,7 @@ Request and Response
lines) at one time, and receive responses for them at one time.
----------------------------------------------------------------------------
'open_index' request
Opening index
The 'open_index' request has the following syntax.
......@@ -74,23 +74,21 @@ FILETER is a sequence of the following parameters.
HandlerSocket supports '=', '>', '>=', '<', and '<='.
- <vlen> indicates the length of the trailing parameters <v1> ... <vn>. This
must be smaller than or equal to the number of index columns specified by
the <columns> parameter of the corresponding 'open_index' request.
the <indexname> parameter of the corresponding 'open_index' request.
- <v1> ... <vn> specify the index column values to fetch.
- LIM is optional. <limit> and <offset> are numbers. When omitted, it works
as if 1 and 0 are specified. These parameter works like LIMIT of SQL.
These values don't include the number of records skipped by a filter.
- IN is optional. It works like WHERE ... IN syntax of SQL. <icol> must be
smaller than or equal to the number of index columns specified by the
<columns> parameter of the corresponding 'open_index' request. If IN is
specified in a find request, the <icol>-th parameter value of <v1> ...
<vn> is ignored.
smaller than or equal to the number of index columns specified by the
smaller than the number of index columns specified by the <indexname>
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.
- 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
<fcol> must be smaller than 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.
----------------------------------------------------------------------------
......@@ -112,8 +110,8 @@ MOD is a sequence of the following parameters.
<mk> must be smaller than or equal to the length of <columns> specified by
the corresponding 'open_index' request. If <mop> is 'D', these parameters
are ignored. 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.
'-' and it attempts to change a column value from negative to positive or
positive to negative, the column value is not modified.
----------------------------------------------------------------------------
Inserting data
......@@ -187,6 +185,8 @@ syntax.
0 1 <nummod>
- <nummod> is the number of modified rows.
- As an exception, if the '?' suffix is specified in <mop>, a response has
the syntax of a response for 'find' instead.
----------------------------------------------------------------------------
Response for 'insert'
......@@ -196,3 +196,10 @@ syntax.
0 1
----------------------------------------------------------------------------
Response for 'auth'
If 'auth' is succeeded, HanderSocket returns a line of the following syntax.
0 1
......@@ -8,7 +8,8 @@ HandlerSocketプラグインのビルド方法(RPMを使わない方法)
$ ./configure --with-mysql-source=/work/mysql-5.1.50 --with-mysql-bindir=/work/mysql-5.1.50-linux-x86_64-glibc23/bin --with-mysql-plugindir=/work/mysql-5.1.50-linux-x86_64-glibc23/lib/plugin
ここで--with-mysql-sourceにはMySQLのソースコードのトップディレク
トリを指定します。--with-mysql-bindirにはインストール済みのMySQL
トリを指定します(そこにVERSIONファイルかconfigure.inファイルがなく
てはなりません)。--with-mysql-bindirにはインストール済みのMySQL
のmysql_configコマンドが有るディレクトリを指定します。
その後以下のようにビルド・インストールします。
......
......@@ -86,7 +86,6 @@ execute_singleメソッドは列の挿入にも使用できます。
my $res = $hs->execute_single(3, '+', [ 'foo', 'bar', 'baz' ]);
die $hs->get_error() if $res->[0] != 0;
my $num_inserted_rows = $res->[1];
第3引数は、対応するopen_index呼び出しの第5引数の列リストと同じだ
けの長さの配列への参照でなければなりません。open_index呼び出しの
......@@ -109,6 +108,15 @@ execute_multiメソッドを使えば、複数のリクエストを一つの呼
# ...
}
-----------------------------------------------------------------
もしhandlersocketが接続を認証するように設定されている
(handlersocket_plain_secret又はhandlersocket_plain_secret_wrがセッ
トされている)ならば、クライアントは他のメソッド呼び出しの前にauth
メソッドを呼び出す必要があります。
my $res = $hs->auth('password');
die $hs->get_error() if $res->[0] != 0;
-----------------------------------------------------------------
エラーが起こると返値の配列参照の最初の要素が0以外になります。負の
数の場合はI/Oエラーが起こったことを示し、その場合はその
......
-----------------------------------------------------------------
----------------------------------------------------------------------------
handlersocketの通信プロトコル
-----------------------------------------------------------------
構文
----------------------------------------------------------------------------
基本的な構文
コマンド行は改行(LF)で終わる。
コマンド行は複数のトークンからなり、トークン間はTABで区切られる。
HandlerSocketのプロトコルは行ベース。各行は改行文字(0x0a)で終わる。
各行は複数のトークンからなり、トークン間はTAB文字(0x09)で区切られる。
・トークンはNULLトークンか、文字列トークンのいずれか。
・NULLトークンは単一のNUL文字であらわされる。
・文字列トークンは、0バイト以上の文字列であらわされる。ただし0x10
未満の文字については0x01を前置し、0x40を加えたコードであらわさ
れる。それ以外の文字はその文字自身のコードであらわされる。
・NULLトークンは単一のNUL文字(0x00)であらわされる。
・文字列トークンは、0バイト以上の文字列であらわされる。ただし0x10未満の文字
については0x01を前置し、0x40を加えたコードであらわされる。それ以外の文字は
その文字自身のコードであらわされる。
-----------------------------------------------------------------
----------------------------------------------------------------------------
リクエストとレスポンス
・接続が確立した直後の状態では、まずクライアントがコマンド行を送
る。(リクエスト)
・サーバはクライアントが送ったリクエストと丁度同じ数のコマンド行
を返す。(レスポンス)
・リクエストはパイプライン化してよい。つまりクライアントは前に
送ったリクエストに対する返事を待たずに次のリクエストを送っても
よい。
-----------------------------------------------------------------
リクエスト
・open_index命令は次のような構文を持つ。
'P' indexid dbname tablename indexname fieldlist
indexidは開いている索引に付けられる番号で、同一接続上で後に実行
する命令の、対象索引を指定するために使われる。dbname、tablename、
indexnameはそれぞれ開きたいDB、テーブル、索引の名前。索引の名前
として"PRIMARY"を指定するとプライマリキーが開かれる。fieldlist
はカンマ区切りの列名のリスト。
・find命令は次のような構文を持つ。
indexid op nflds v1 ... vn limit offset
indexidは実行対象の索引を指定する。opは索引検索の演算子(後述)。
v1からvnは可変長で、その個数はnflds。nfldsはindexidで指定された
open_index命令のindexnameの索引のfieldlistのフィールド数に等し
いか小さくなくてはならない。m2からmkは可変長で、その個数は
indexidで指定されたopen_index命令が発行された際のfieldlistに一
致しなければならない。コマンド行のlimit以降は省略できる。limit
とoffsetは、検索条件に合致する列のうちレスポンスに返す列数の上
限と、スキップする列数。limitとoffsetを省略した場合はそれぞれ1
と0が指定されたときと同じ動作をする。find命令はレスポンスとして、
条件に合致した列のリストを返す。opとして指定できる演算子は次の
とおり。
'=' - v1 ... vnと一致するものを取得
'>' - v1 ... vnより大きいものを昇順に取得
'>=' - v1 ... vnに一致するか大きいものを昇順に取得
'<' - v1 ... vnより小さいものを降順に取得
'<=' - v1 ... vnに一致するか等しいものを降順に取得
nfldsが1より大きい(v1 ... vnが2個以上)ときは辞書式順序で比較さ
れる。
・find_modify命令は次のような構文を持つ。
indexid op nflds v1 ... vn limit offset modop m1 ... mk
modopより前の部分はfind命令と同等で、これによって操作対象の行を
指定する。その操作対象の行に対しmodopで指定された変更処理を実行
する。m1 ... mkは可変長で、省略できる。modopは次いずれか。
'U' - indexidで指定されたopen_index命令のfieldlist列
の内容を、m1 ... mkの値で更新する。
'D' - 対象の行を削除する。m1 ... mkの値は無視される。
・insert命令はのような構文を持つ。
indexid '+' nflds v1 ... vn
indexidで指定されたテーブルに、列を挿入する。v1 ... vnは可変長
で、その個数はnflds。nfldsはindexidで指定されたopen_index命令の
indexnameの索引のfieldlistのフィールド数に等しいか小さくなくて
はならない。
-----------------------------------------------------------------
レスポンス
・open_index命令が成功したとき、レスポンスは次の構文を持つ。
'0' '1'
・find命令が成功したとき、レスポンスは次の構文を持つ。
'0' nflds v1 ... vn
nfldsは結果セットの列の数をあらわす。v1 ... vnは可変長で、その
長さはnfldsの整数倍。v1 ... vnは空のこともあり、それは条件に合
致するレコードが存在しなかったことをあらわす。結果セットが複数
行になったときはv1 ... vnの長さがnfldsの2倍以上となり、最初の
行から順にv1 ... vnにセットされる。
・modify命令が成功したとき、レスポンスは次の構文を持つ。
'0' '1' nummod
nummodは変更が施された行数。nummodが0のときは変更された行が無
かったことをあらわす。
・insert命令が成功したとき、レスポンスは次の構文を持つ。
'0' '1'
・命令が失敗したとき、レスポンスは命令に関わらず次の構文を持つ。
err '1' message
errは0以外の数値で、エラーコードをあらわす。messageは人間可読な
エラーメッセージ。ただしmessageが無いこともある。
・HandlerSocketのプロトコルは単純なリクエスト・レスポンスプロトコルになって
いる。接続が確立した後は、まずクライアントがリクエストを送る。
・サーバは、クライアントが送ったリクエストと丁度同じ数の行(レスポンス)を返
す。
・リクエストはパイプライン化してよい。つまりクライアントは前に送ったリクエス
トに対する返事(レスポンス)を待たずに次のリクエストを送ってもよい。
----------------------------------------------------------------------------
インデックスを開く
open_index命令は次のような構文を持つ。
P <indexid> <dbname> <tablename> <indexname> <columns> [<fcolumns>]
- <indexid>は数字で、同一接続上で後に実行する命令の、対象索引を指定するため
に使われる。
- <dbname>, <tablename>, <indexname>は文字列で、それぞれDB名、テーブル名、
索引の名前を指定する。<indexname>として「PRIMARY」を指定するとプライマリ
キーが開かれる。
- <columns>はカンマ区切りの列名のリスト。
- <fcolumns>はカンマ区切りの列名のリスト。これは省略することができる。
このopen_index命令が実行されると、HandlerSocketプラグインは指定されたDB、
テーブル、索引を開く。開かれた索引は接続が閉じられるまで開かれたままになる。
開かれた索引は<indexid>の数字で識別される。もし既に<indexid>に指定された番号
の索引が既に開かれている場合は古いほうが閉じられる。この<indexid>はなるべく
小さな数字を使ったほうが効率が良い。
----------------------------------------------------------------------------
データ取得
find命令は次のような構文を持つ。
<indexid> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER ...]
LIMは次のようなパラメータの並び
<limit> <offset>
INは次のようなパラメータの並び
@ <icol> <ivlen> <iv1> ... <ivn>
FILTERは次のようなパラメータの並び
<ftyp> <fop> <fcol> <fval>
- <indexid>は数字で、これは同じ接続上で過去に実行したopen_index命令に指定さ
れた数字でなければならない。
- <op>は比較演算子で、現在のバージョンでは '=', '>', '>=', '<', '<=' をサ
ポートしている。
- <vlen>は後に続くパラメータ<v1> ... <vn>の長さ。この値は対応するopen_index
命令の<indexname>パラメータで指定された索引のキー列の数と同じか小さいもの
でなければならない。
- <v1> ... <vn>は取得するべきキーの値を指定するパラメータ。
- LIMは省略できる。<limit>と<offset>は数字で、これはSQLのLIMITと同じように
はたらく。省略した場合は1と0を指定した場合と同じ動作をする。FILTERによっ
て読み飛ばされたレコードは<limit>と<offset>にカウントされない。
- INは省略できる。指定されると、これはSQLの WHERE ... IN のように動作する。
<icol>は対応するopen_index命令の<indexname>パラメータで指定された索引の
キー列の数より小さいものでなければならない。INが指定されたときは、find命
令の<v1> ... <vn>のうち<icol>番目の値は無視される。
- FILTERは省略できる。これは行取得の際のフィルタを指定する。<ftyp>は
'F'(filter)か'W'(while)のいずれかでなければならない。<fop>は比較演算子。
<fcol>は数字で、これは対応するopen_index命令の<fcolumns>で指定された列の
数より小さいものでなければならない。複数のフィルタを指定することもでき、
その場合は各フィルタのANDと解釈される。'F'と'W'の違いは、条件にあてはま
らない行があったときに'F'は単にそれをスキップするが、'W'はその時点でルー
プを抜けるという点。
----------------------------------------------------------------------------
更新と削除
find_modify命令は次のような構文を持つ。
<indexid> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER ...] MOD
MODは次のようなパラメータの並び
<mop> <m1> ... <mk>
- <mop>は'U', '+', '-', 'D', 'U?', '+?', '-?', 'D?'のいずれか。'?'が付いた
ものは付いていないものとほぼ同じ動作をするが、付いていないものがレスポン
スとして更新された行の数を返すのに対し、付いているものは更新される前の行
の内容を返す点のみが異なる。'U'は更新、'D'は削除、'+'はインクリメント、
'-'はデクリメントを実行する。
- <m1> ... <mk>はセットされる各列の値。<m1> ... <mk>の長さは対応する
open_index命令の<columns>の長さと等しいか小さくなければならない。<mop>が
'D'のときはこれらのパラメータは無視される。<mop>が'+'か'-'のときは、これら
の値は数値でなければならない。<mop>が'-'で、それが負数から正数、または正数
から負数へ列の値を変更するようなものであった場合は、値は変更されない。
----------------------------------------------------------------------------
行の挿入
insert命令は次のような構文を持つ。
<indexid> + <vlen> <v1> ... <vn>
- <vlen>は後に続くパラメータ<v1> ... <vn>の長さ。これは対応するopen_indexの
<columns>の長さに等しいか小さくなければならない。
- <v1> ... <vn>はセットされる各列の値。指定されないかった列についてはその列
のデフォルト値がセットされる。
----------------------------------------------------------------------------
認証
auth命令は次のような構文を持つ。
A <atyp> <akey>
- <atyp>は現在のバージョンでは'1'のみが有効。
- 指定された<akey>が、サーバの設定の'handlersocket_plain_secret'や
'handlersocket_plain_secret_wr'に指定された文字列と一致した場合にのみ認証
は成功する。
- HandlerSocketの認証が有効になっているときは、この'auth'が成功しない限りそ
れ以外の命令は全て失敗する。
----------------------------------------------------------------------------
open_indexに対するレスポンス
open_index命令が成功したとき、レスポンスは次の構文を持つ。
0 1
----------------------------------------------------------------------------
findに対するレスポンス
find命令が成功したとき、レスポンスは次の構文を持つ。
0 <numcolumns> <r1> ... <rn>
- <numcolumns>はfind命令の対応するopen_index命令に指定した<columns>の長さに
一致する。
- <r1> ... <rn>は結果セット。もしN行がfind命令で見つかったなら、<r1> ...
<rn>の長さは ( <numcolumns> * N )になる。
----------------------------------------------------------------------------
find_modifyに対するレスポンス
find_modify命令が成功したとき、レスポンスは次の構文を持つ。
0 1 <nummod>
- <nummod>は変更された行の数。
- 例外として、<mop>が'?'の付いたものであった場合には、find命令に対するレスポ
ンスと同じ構文のレスポンスを返す。
----------------------------------------------------------------------------
insertに対するレスポンス
insert命令が成功したとき、レスポンスは次の構文を持つ。
0 1
----------------------------------------------------------------------------
authに対するレスポンス
auth命令が成功したとき、レスポンスは次の構文を持つ。
0 1
......@@ -658,7 +658,7 @@ dbcontext::cmd_insert_internal(dbcallback_i& cb, const prep_stmt& pst,
empty_record(table);
memset(buf, 0, table->s->null_bytes); /* clear null flags */
const prep_stmt::fields_type& rf = pst.get_ret_fields();
const size_t n = rf.size();
const size_t n = std::min(rf.size(), fvalslen);
for (size_t i = 0; i < n; ++i) {
uint32_t fn = rf[i];
Field *const fld = table->field[fn];
......
......@@ -151,7 +151,7 @@ sv_get_string_ref(SV *sv)
static IV
sv_get_iv(SV *sv)
{
if (sv == 0 || !SvIOK(sv)) {
if (sv == 0 || ( !SvIOK(sv) && !SvPOK(sv) ) ) {
return 0;
}
return SvIV(sv);
......
#!/bin/bash
TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23";
TESTS="01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24";
source ../common/compat.sh
......
......@@ -27,7 +27,7 @@ srand(999);
my %valmap = ();
my $sth = $dbh->prepare("insert into $table values (?,?,?)");
my $sth = $dbh->prepare("insert ignore into $table values (?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $k = $i;
my ($s1, $s2) = ("", "");
......
......@@ -60,7 +60,7 @@ sub test_one {
$dbh->do(
"create table $table (" .
"k $typ, " .
"v1 varchar(2047), " .
"v1 varchar(1000), " .
"v2 $typ, " .
"primary key(k$keylen_str), " .
"index i1(v1), index i2(v2$keylen_str, v1(300))) " .
......
......@@ -113,7 +113,7 @@ sub test_one {
"(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 (?,?,?,?)");
my $sth = $dbh->prepare("insert ignore into $table values (?,?,?,?)");
for (my $i = 0; $i < $tablesize; ++$i) {
my $j = 0;
for my $v (@$values) {
......
#!/usr/bin/perl
# vim:sw=2:ai
# test for issue #78
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 (" .
"id bigint(20) not null auto_increment, " .
"t1 timestamp not null default current_timestamp, " .
"primary key (id)" .
") engine = innodb");
srand(999);
my %valmap = ();
my $hs = hstest::get_hs_connection(undef, 9999);
my $dbname = $hstest::conf{dbname};
$hs->open_index(0, $dbname, $table, 'PRIMARY', 'id,t1');
my $res = $hs->execute_single(0, '+', [ 321 ], 0, 0);
die $hs->get_error() if $res->[0] != 0;
print "HS\n";
print join(' ', @$res) . "\n";
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