我一直在为CQL3.0编写Cassandra cppdriver的包装器,我遇到了一些奇怪的行为,我不确定它是典型的还是错误的。
作为参考,我正在使用9月4日(来自存储库)的cppdriver代码版本,libuv0.10以及发布在datastax网站上的歌曲/播放列表示例(http://www.datastax.com/documentation/cql/3.1/cql/ddl/ddl_music_service_c.html)
我遇到的问题是执行查询字符串。似乎有一些字符的阈值,之后发送到Cassandra的查询字符串变为垃圾。下面提供了我用来构造字符串并将字符串发送到cppdriver库(并解析结果)的代码。我在cassandra.h和session.cpp文件中添加了一个函数(cass_session_print_query)来打印出生成的语句。
map<string, vector<string> > retresults;
int i = 0, ccount;
stringstream ss;
vector<string> keys = get.GetList();
vector<string>::iterator kit = keys.begin();
map<int, pair<string, string> > primkeys = get.GetMap();
map<int, pair<string, string> >::iterator mit = primkeys.begin();
if (!keys.empty())
{
ss << "SELECT " << (*kit);
++kit;
for ( ; kit != keys.end(); ++kit)
ss << "," << (*kit);
ss << " FROM " << tablename;
if (!primkeys.empty())
{
ss << " WHERE ";
ss << mit->second.first << " = ?";
++mit;
for ( ; mit != primkeys.end(); ++mit)
ss << " and " << mit->second.first << " = ?";
mit = primkeys.begin();
}
ss << ";";
cass_bool_t has_more_pages = cass_false;
const CassResult* result = NULL;
CassString query = cass_string_init(ss.str().c_str());
CassStatement* statement = cass_statement_new(query, primkeys.size());
for ( ; mit != primkeys.end(); ++mit)
cass_statement_bind_string(statement, i++, cass_string_init(mit->second.second.c_str()));
cass_statement_set_paging_size(statement, 100);
do
{
cass_session_print_query(statement);
CassIterator* iterator;
CassFuture* future = cass_session_execute(session_, statement);
if (cass_future_error_code(future) != 0)
{
CassString message = cass_future_error_message(future);
fprintf(stderr, "Error: %.*s\n", (int)message.length, message.data);
break;
}
result = cass_future_get_result(future);
ccount = cass_result_column_count(result);
vector<string> cnames;
for (i = 0; i < ccount; i++)
cnames.push_back(cass_result_column_name(result, i).data);
iterator = cass_iterator_from_result(result);
ListVector::iterator vit;
while (cass_iterator_next(iterator))
{
const CassRow* row = cass_iterator_get_row(iterator);
for (vit = cnames.begin(); vit != cnames.end(); ++vit)
{
CassString value;
char value_buffer[256];
cass_value_get_string(cass_row_get_column_by_name(row, (*vit).c_str()), &value);
if (value.length == 0 || value.data == NULL)
continue;
memcpy(value_buffer, value.data, value.length);
value_buffer[value.length] = '\0';
retresults[(*vit)].push_back(value_buffer);
}
}
has_more_pages = cass_result_has_more_pages(result);
if (has_more_pages)
cass_statement_set_paging_state(statement, result);
cass_iterator_free(iterator);
cass_result_free(result);
} while (has_more_pages);
}
return retresults;
有了这个,SELECT id,album,title,artist,data FROM songs;
的初始查询字符串会产生SELECT id,album,title,artist,data FROM songs;
的Cassandra查询字符串。但是,如果我再向SELECT部分SELECT id,album,title,artist,data,tags FROM songs;
添加一列,则Cassandra cppdriver库中的查询字符串将变为:,ar����,dat�� jOM songX
。这会导致Cassandra /库出现以下错误:Error: line 1:49 no viable alternative at character '�'
。
我也尝试过更少的列,但是使用WHERE子句,这会导致同样的问题。
这是一个错误吗?或者我是否错误地构建并向cppdriver库发送字符串?
答案 0 :(得分:3)
所以,看起来(无论出于什么原因)我必须从结果中解析出行键。我检查了这个例子,我无法解析行密钥信息,一切仍然有效。我还不完全确定是什么迫使我这样做(与提供的分页示例相比),但对于其他人,您需要在while (cass_iterator_nex(iterator))
块中包含以下内容以“神奇地”修复上面的代码。< / p>
CassUuid key;
char key_buffer[CASS_UUID_STRING_LENGTH];
const CassRow* row = cass_iterator_get_row(iterator);
cass_value_get_uuid(cass_row_get_column(row, 0), key);
cass_uuid_string(key, key_buffer);
答案 1 :(得分:3)
在测试错误代码之前,你应该对执行的未来进行cass_future_wait()。
无关:还有一些事情应该被释放(未来,陈述),但我认为这样做是为了保持这种简洁而被省略。
答案 2 :(得分:0)
这真是一个很长的镜头,但是既然你提到了音乐服务的例子,你是否可以下载并使用cql_collections.zip查询字符串?如果是这样,字符串(现在已修复)有较小的语法错误:
-use music -CREATE TABLE music.songs ( id uuid PRIMARY KEY, album text, artist text, data blob, reviews list, tags set, title text, venue map +use music; +CREATE TABLE music.songs ( id uuid PRIMARY KEY, album text, artist text, data blob, reviews list, tags set, title text, venue map);
答案 3 :(得分:0)
AeroBuffalo的代码对我有用,除了我不得不放'&amp;'在cass_value_get_uuid()函数的第二个参数前面。它需要参考类型。
cass_value_get_uuid(cass_row_get_column(row, 0), &key);