Skip to content

Commit

Permalink
Add necessary implementation to pass all BasicsTests
Browse files Browse the repository at this point in the history
Added implementation of cass_value_get_bytes to retrieve bytes of
a Blob value.

Added paging state token setter for CassStatement.

Added paging state token getter from query result.
  • Loading branch information
Gor027 committed Aug 2, 2022
1 parent 7ea8aaf commit 23c2f49
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ jobs:
run: cmake -DCASS_BUILD_INTEGRATION_TESTS=ON . && make

- name: Run integration tests on Scylla 5.0.0
run: valgrind --error-exitcode=123 ./cassandra-integration-tests --version=release:5.0.0 --category=CASSANDRA --verbose=ccm --gtest_filter="ClusterTests.*:BasicsTests.*RowsInRowsOut"
run: valgrind --error-exitcode=123 ./cassandra-integration-tests --version=release:5.0.0 --category=CASSANDRA --verbose=ccm --gtest_filter="ClusterTests.*:BasicsTests.*"
2 changes: 1 addition & 1 deletion scylla-rust-wrapper/src/prepared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub unsafe extern "C" fn cass_prepared_free(prepared_raw: *const CassPrepared) {
pub unsafe extern "C" fn cass_prepared_bind(
prepared_raw: *const CassPrepared,
) -> *mut CassStatement {
let prepared: Arc<_> = Arc::from_raw(prepared_raw);
let prepared: Arc<_> = clone_arced(prepared_raw);
let bound_values_size = prepared.get_prepared_metadata().col_count;

// cloning prepared statement's arc, because creating CassStatement should not invalidate
Expand Down
85 changes: 84 additions & 1 deletion scylla-rust-wrapper/src/query_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use crate::argconv::*;
use crate::cass_error::CassError;
use crate::cass_types::{cass_data_type_type, CassDataType, CassValueType};
use crate::inet::CassInet;
use crate::statement::CassStatement;
use crate::types::*;
use crate::uuid::CassUuid;
use scylla::frame::response::result::{ColumnSpec, CqlValue};
use scylla::Bytes;
use scylla::{Bytes, BytesMut};
use std::convert::TryInto;
use std::os::raw::c_char;
use std::slice;
use std::sync::Arc;

pub struct CassResult {
Expand Down Expand Up @@ -401,6 +403,30 @@ pub unsafe extern "C" fn cass_value_get_string(
CassError::CASS_OK
}

#[no_mangle]
pub unsafe extern "C" fn cass_value_get_bytes(
value: *const CassValue,
output: *mut *const cass_byte_t,
output_size: *mut size_t,
) -> CassError {
if value.is_null() {
return CassError::CASS_ERROR_LIB_NULL_VALUE;
}

let value_from_raw: &CassValue = ptr_to_ref(value);

match &value_from_raw.value {
Some(CqlValue::Blob(bytes)) => {
*output = bytes.as_ptr() as *const cass_byte_t;
*output_size = bytes.len() as u64;
}
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
None => return CassError::CASS_ERROR_LIB_NULL_VALUE,
}

CassError::CASS_OK
}

#[no_mangle]
pub unsafe extern "C" fn cass_value_is_null(value: *const CassValue) -> cass_bool_t {
let val: &CassValue = ptr_to_ref(value);
Expand Down Expand Up @@ -436,6 +462,63 @@ pub unsafe extern "C" fn cass_result_first_row(result_raw: *const CassResult) ->
std::ptr::null()
}

#[no_mangle]
pub unsafe extern "C" fn cass_result_paging_state_token(
result: *const CassResult,
paging_state: *mut *const c_char,
paging_state_size: *mut size_t,
) -> CassError {
if cass_result_has_more_pages(result) == cass_false {
return CassError::CASS_ERROR_LIB_NO_PAGING_STATE;
}

let result_from_raw = ptr_to_ref(result);

if result_from_raw.metadata.paging_state.is_none() {
*paging_state_size = 0;
*paging_state = std::ptr::null();
} else {
*paging_state_size = result_from_raw
.metadata
.paging_state
.as_ref()
.unwrap()
.len() as u64;
*paging_state = result_from_raw
.metadata
.paging_state
.clone()
.unwrap()
.as_ptr() as *const c_char;
}

CassError::CASS_OK
}

#[no_mangle]
pub unsafe extern "C" fn cass_statement_set_paging_state_token(
statement: *mut CassStatement,
paging_state: *const c_char,
paging_state_size: size_t,
) -> CassError {
let statement_from_raw = ptr_to_ref_mut(statement);

if paging_state.is_null() {
statement_from_raw.paging_state = None;
return CassError::CASS_ERROR_LIB_NULL_VALUE;
}

let paging_state_usize: usize = paging_state_size.try_into().unwrap();
let mut b = BytesMut::from(slice::from_raw_parts(
paging_state as *const u8,
paging_state_usize,
));
b.extend_from_slice(b"\0");
statement_from_raw.paging_state = Some(b.freeze());

CassError::CASS_OK
}

// CassResult functions:
/*
extern "C" {
Expand Down
19 changes: 19 additions & 0 deletions scylla-rust-wrapper/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,22 @@ pub unsafe extern "C" fn cass_session_prepare_n(
pub unsafe extern "C" fn cass_session_free(session_raw: *mut CassSession) {
free_arced(session_raw);
}

#[no_mangle]
pub unsafe extern "C" fn cass_session_close(session: *mut CassSession) -> *const CassFuture {
let session_opt = ptr_to_ref(session);

CassFuture::make_raw(async move {
let mut session_guard = session_opt.write().await;
if session_guard.is_none() {
return Err((
CassError::CASS_ERROR_LIB_UNABLE_TO_CLOSE,
"Already closing or closed".msg(),
));
}

*session_guard = None;

Ok(CassResultValue::Empty)
})
}
29 changes: 0 additions & 29 deletions src/testing_unimplemented.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,19 +477,6 @@ cass_prepared_parameter_data_type_by_name(const CassPrepared* prepared,
const char* name){
throw std::runtime_error("UNIMPLEMENTED cass_prepared_parameter_data_type_by_name\n");
}
CASS_EXPORT CassError
cass_result_column_name(const CassResult *result,
size_t index,
const char** name,
size_t* name_length){
throw std::runtime_error("UNIMPLEMENTED cass_result_column_name\n");
}
CASS_EXPORT CassError
cass_result_paging_state_token(const CassResult* result,
const char** paging_state,
size_t* paging_state_size){
throw std::runtime_error("UNIMPLEMENTED cass_result_paging_state_token\n");
}
CASS_EXPORT CassRetryPolicy*
cass_retry_policy_default_new(){
throw std::runtime_error("UNIMPLEMENTED cass_retry_policy_default_new\n");
Expand Down Expand Up @@ -529,10 +516,6 @@ cass_schema_meta_version(const CassSchemaMeta* schema_meta){
throw std::runtime_error("UNIMPLEMENTED cass_schema_meta_version\n");
}
CASS_EXPORT CassFuture*
cass_session_close(CassSession* session){
throw std::runtime_error("UNIMPLEMENTED cass_session_close\n");
}
CASS_EXPORT CassFuture*
cass_session_connect_keyspace(CassSession* session,
const CassCluster* cluster,
const char* keyspace){
Expand Down Expand Up @@ -677,12 +660,6 @@ cass_statement_set_node(CassStatement* statement,
throw std::runtime_error("UNIMPLEMENTED cass_statement_set_node\n");
}
CASS_EXPORT CassError
cass_statement_set_paging_state_token(CassStatement* statement,
const char* paging_state,
size_t paging_state_size){
throw std::runtime_error("UNIMPLEMENTED cass_statement_set_paging_state_token\n");
}
CASS_EXPORT CassError
cass_statement_set_request_timeout(CassStatement* statement,
cass_uint64_t timeout_ms){
throw std::runtime_error("UNIMPLEMENTED cass_statement_set_request_timeout\n");
Expand Down Expand Up @@ -808,12 +785,6 @@ cass_user_type_set_duration_by_name(CassUserType* user_type,
throw std::runtime_error("UNIMPLEMENTED cass_user_type_set_duration_by_name\n");
}
CASS_EXPORT CassError
cass_value_get_bytes(const CassValue* value,
const cass_byte_t** output,
size_t* output_size){
throw std::runtime_error("UNIMPLEMENTED cass_value_get_bytes\n");
}
CASS_EXPORT CassError
cass_value_get_decimal(const CassValue* value,
const cass_byte_t** varint,
size_t* varint_size,
Expand Down
2 changes: 1 addition & 1 deletion tests/src/integration/tests/test_basics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ CASSANDRA_INTEGRATION_TEST_F(BasicsTests, UnsetParameters) {

// Execute the insert statement and validate the error code
Result result = session_.execute(insert_statement, false);
if (server_version_ >= "2.2.0") {
if (server_version_ >= "release:2.2.0") {
// Cassandra v2.2+ uses the value UNSET; making this a no-op
ASSERT_EQ(CASS_OK, result.error_code());
} else {
Expand Down

0 comments on commit 23c2f49

Please sign in to comment.