jackeylu / mysql2redis

A UDF(user defined functions) plugin for MySQL, which can be used for pushing data to Redis
53 stars 27 forks source link

Failed to excute redis_command when json filed's value include white space #3

Open gettyying opened 11 years ago

gettyying commented 11 years ago

Like as below:

mysql> select @a := json_object(topic as topic) from test limit 1;
+-----------------------------------+
| @a := json_object(topic as topic) |
+-----------------------------------+
| {"topic":"你 我 他 她"}           |
+-----------------------------------+
1 row in set (0.00 sec)

mysql> set @b := concat("hset \"htest\" \"1\" \"", @a, "\"");
Query OK, 0 rows affected (0.00 sec)

mysql> select @b;
+------------------------------------------------+
| @b                                             |
+------------------------------------------------+
| hset "htest" "1" "{"topic":"你 我 他 她"}"     |
+------------------------------------------------+
1 row in set (0.00 sec)

mysql> select redis_command("127.0.0.1",6379, @b);
+-------------------------------------+
| redis_command("127.0.0.1",6379, @b) |
+-------------------------------------+
|                                   3 |
+-------------------------------------+
1 row in set (0.00 sec)

But it's succeed when wrap off white space.

mysql> select @a := json_object(replace(topic, " " , "") as topic) from test limit 1;
+------------------------------------------------------+
| @a := json_object(replace(topic, " " , "") as topic) |
+------------------------------------------------------+
| {"topic":"你我他她"}                                 |
+------------------------------------------------------+
1 row in set (0.00 sec)

mysql> set @b := concat("hset 'htest' '1' '", @a, "'");
Query OK, 0 rows affected (0.00 sec)

mysql> select redis_command("127.0.0.1",6379, @b);
+-------------------------------------+
| redis_command("127.0.0.1",6379, @b) |
+-------------------------------------+
|                                   0 |
+-------------------------------------+
1 row in set (0.00 sec)
jackeylu commented 11 years ago

With the debugging information,

   $6 = 0x7fb8b7f088e0 "ERR wrong number of arguments for 'hset' command"

you can see that during the call of redisCommand of hiRedis, it reported such error information.

mysql> select @b;

+------------------------------------------+ | @b | +------------------------------------------+ | hset "htest" "1" "{"topic":"h e l l o"}" | +------------------------------------------+ 1 row in set (0.00 sec)

in gdb, you can see that

(gdb) p cmd
$8 = 0x7fb8b869c380 "hset \"htest\" \"1\" \"{\"topic\":\"h e l l o\"}\""

and the redisCommand complaint that with "ERR wrong number of arguments for 'hset' command".

It's illegal to pass white space between mysql SQL and hiredis.

I have two suggestion for you.

  1. you hack the hiredis
  2. replace white space with other character.
gettyying commented 11 years ago

To verify the problem, I did tests using hiredis directly.

reply = redisCommand(c,"SET %s %s", "foo", "{\"topic\" : \"hello world\"}");
printf("The value has white space: %s\n", reply->str);
freeReplyObject(reply);

It's gonna work out fine. Unfortunately, it's failed when transfer keys and values directly, as below:

reply = redisCommand(c,"SET foo {\"topic\" : \"hello world\"}");
printf("The value has white space: %s\n", reply->str);
freeReplyObject(reply);
jackeylu commented 11 years ago

@gettyying thank you for your work.

I patched this in the latest version, let the redis_command can get 3 or 5 parameters.

You can test the new one.

But as the talking in issue/2, the solution from mysql to redis, it is not a very meaningful work. Why we have to take some much time on this?

By the way, the code is open-sourced, you can do it as you want.