2014-09-13 6 views
2

나는 CQL3.0을위한 Cassandra cppdriver에 대한 래퍼를 작성해 왔으며 이상한 행동을 보았습니다. 일반적인 버그인지 확실하지 않습니다. 참고로 Cassandra cppdriver 쿼리 문자열 버퍼 오버플로?

, 나는 (저장소에서) 4- 9 월 cppdriver 코드 릴리스, libuv0.10와 함께하고 datastax 웹 사이트 ( http://www.datastax.com/documentation/cql/3.1/cql/ddl/ddl_music_service_c.html)

문제에 게시 된 곡/재생 목록의 예를 떨어져 있어요 내가 가지고있는 것은 쿼리 문자열을 실행하는 것입니다. 카산드라에게 보내지는 질의 문자열이 쓰레기가되는 문자의 임계 값이있는 것으로 보입니다. 문자열을 생성하고 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; 결과의 초기 쿼리 문자열. 그러나 하나의 열을 SELECT 부분에 추가하면 SELECT id,album,title,artist,data,tags FROM songs; Cassandra cppdriver 라이브러리의 쿼리 문자열은 ,ar����,dat�� jOM songX이됩니다. Cassandra/library에서 다음과 같은 오류가 발생합니다 : Error: line 1:49 no viable alternative at character '�'.

또한 적은 수의 열을 시도했지만 WHERE 절을 사용하면 동일한 문제가 발생합니다.

이것은 버그입니까? 아니면 건물 및 cppdriver 라이브러리에 문자열을 잘못 보내고 있습니까?

+1

나는 당신이보고있는 문제에 대해 잘 모릅니다. 그러나 한 가지주의해야 할 점은 오류 코드를 테스트하기 전에 미래에 cass_future_wait()를 사용해야한다는 것입니다. 또한 해명해야 할 몇 가지가 있습니다 (미래, 성명). 그러나 간결하게하기 위해 생략 된 것으로 가정합니다. –

+0

cass_future_wait (미래) 문제가있었습니다. 감사! 이 질문을 답안에 쓰고 싶으면 그 답으로 표시 할 것입니다. – AeroBuffalo

답변

3

오류 코드를 테스트하기 전에 실행을 미리 cass_future_wait()해야합니다.

무관계 : 해방되어야 할 몇 가지 (미래, 진술)이지만, 간결하게하기 위해 생략 된 것으로 가정합니다.

+0

다른 사람들을 위해, 저는 또한'CassString query = cass_string_init (..)'변수를 가지고'cass_statement_new()'함수에 넘겨 주면 문제가 생기는 것을 발견했습니다. 대신, 새로운 Cassandra 명령문 함수의 첫 번째 인수로'cass_string_init()'함수를 "전달"하십시오. – AeroBuffalo

+0

예기치 않습니다. 쉽게 입증 할 수 있다면 문제를 보여주는 티켓을 여는 것이 좋습니까? https : //datastax-oss.atlassian.net/browse/CPP –

+0

원한다면 할 수 있습니다. 그러나 상황은 복잡합니다. Python Flask HTTP API -> C++ 처리 파일 (파이썬 오브젝트를 맵 및 벡터로 변환) -> cppdriver 래퍼 클래스. 원래의 질문). 여전히 좋은 쟁점이 있다면 게시하겠습니다. – AeroBuffalo

0

이것은 매우 길지만, Music Service 예제를 언급 한 이후로 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); 
+0

cql_collections.zip은 종을 울리지 않으므로 결코 사용하지 않았다고 확신합니다. – AeroBuffalo

2

는 그래서, 내가 결과에서 행 키를 구문 분석 할 필요가 같은 (어떤 이유) 모양 : 그렇다면, 현 (현재 고정)는 사소한 구문 오류가 있었다. 예제를 살펴본 결과 행 키 정보를 파싱 할 수 없었고 모든 것이 여전히 작동했습니다. 나는 (제공된 페이징 예제와 비교할 때) 내가 무엇을하도록 강요하고 있는지 아직 확실히 모르겠다. 그러나 다른 사람들은 위의 코드를 "마술처럼"수정하기 위해 while (cass_iterator_nex(iterator)) 블록 내에 다음을 포함시켜야한다.

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);