MySQL c ++连接器:使用SetBlob()在查询中设置多个blob数据的正确方法是什么?

时间:2017-08-25 03:36:57

标签: c++ mysql c++11

我在stackexchange数据库管理员问了同样的问题,这似乎是问题的正确位置,但问题是甚至没有人查看问题。所以我再次在这里发布同样的问题:

我正在研究Mysql表插入。表创建语句如下:

CREATE TABLE files_table (fid INT NOT NULL AUTO_INCREMENT, idx TINYBLOB, head TINYBLOB, size BLOB, PRIMARY KEY(fid));

我可以手动插入记录

mysql> select * from files_table order by fid asc;
+-----+------+------+------------+
| fid | idx  | head | size       |
+-----+------+------+------------+
|   1 | 1    | 1    | 1          |
+-----+------+------+------------+

但是当我使用连接器通过使用c ++连接器添加下一个值时:

class StreamBufferData : public std::streambuf
{
public:
    StreamBufferData(const char *in_data, size_t in_size)
    {
        setg(in_data, in_data, in_data + in_size);
    }
};

enum{QUERY_SIZE=256;}
char ins[QUERY_SIZE];

strcpy(ins, "INSERT INTO files_table (idx, head, size) VALUES (?,?,?)");

try
{
    std::unique_ptr<sql::PreparedStatement> statement(ptr_connection->prepareStatement(ins));

    char test_data[2] = "0";
    StreamBufferData buffer0(test_data, 2);
    std::istream test_s0(&buffer0);
    statement->setBlob(1, &test_s0);

    strcpy(test_data, "1");
    StreamBufferData buffer1(test_data, 2);
    std::istream test_s1(&buffer1);
    statement->setBlob(2, &test_s1);

    strcpy(test_data, "2");
    StreamBufferData buffer2(test_data, 2);
    std::istream test_s2(&buffer2);
    statement->setBlob(3, &test_s2);

    statement->executeUpdate();
}
catch(sql::SQLException &e)
{
    std::cout << e.what() << ‘\n’; 
    return;
}

结果是:

+-----+------+------+------------+
| fid | idx  | head | size       |
+-----+------+------+------------+
|   1 | 1    | 1    | 1          |
|   2 | 2    | 2    | 2          |
+-----+------+------+------------+

只有最后一个值正确插入表中。我的问题是:用户msql :: PreparedStatement :: setBlob()在查询中设置多个blob的正确方法是什么?

[环境]
Ubuntu 16.04.2
MySQL 5.7
MySQL连接器版本:7.1.1.7
提升1.58.0
g ++ 5.4.0

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

不同的std::istream对象指向由test_data分配的同一缓冲区。我以为istream对象将复制char数组中的值。事实是,它不是。

值得指出的是,如果在执行statement-&gt; executeUpdate()之前销毁了std :: istream对象。最后一个流对象将填充到表的第一列,这可能是我的机器上的未定义行为(Ubuntu 16.04.2 LTS)。它看起来像:

+-----+------+------+------------+
| fid | idx  | head | size       |
+-----+------+------+------------+
|   1 | 1    | 1    | 1          |
|   2 | 2    |      |            |
+-----+------+------+------------+

因此,如果表具有与前一个表类似的奇怪结果,请检查代码以确保std :: stream,StreamBufferData和指向缓冲区的指针在执行statement-&gt; executeUpdate()之前仍然有效。