Skip to content

Commit ee867e3

Browse files
authored
Merge pull request #135 from muzarski/cass_value_get_duration
types: Implement API functions for `duration` type
2 parents 720fdad + e89b178 commit ee867e3

File tree

9 files changed

+98
-105
lines changed

9 files changed

+98
-105
lines changed

README.md

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,11 @@ The driver inherits almost all the features of C/C++ and Rust drivers, such as:
160160
</tr>
161161
<tr>
162162
<td>cass_statement_bind_custom[by_name]</td>
163-
<td rowspan="3">Binding is not implemented for custom types in the Rust driver. <br> Binding Decimal and Duration types requires encoding raw bytes into BigDecimal and CqlDuration types in the Rust driver. <br> <b>Note</b>: The driver does not validate the types of the values passed to queries.</td>
163+
<td rowspan="2">Binding is not implemented for custom types in the Rust driver. <br> Binding Decimal type requires encoding raw bytes into BigDecimal type in the Rust driver. <br> <b>Note</b>: The driver does not validate the types of the values passed to queries.</td>
164164
</tr>
165165
<tr>
166166
<td>cass_statement_bind_decimal[by_name]</td>
167167
</tr>
168-
<tr>
169-
<td>cass_statement_bind_duration[by_name]</td>
170-
</tr>
171168
<tr>
172169
<td colspan=2 align="center" style="font-weight:bold">Future</td>
173170
</tr>
@@ -190,40 +187,27 @@ The driver inherits almost all the features of C/C++ and Rust drivers, such as:
190187
</tr>
191188
<tr>
192189
<td>cass_collection_append_custom[_n]</td>
193-
<td rowspan="3">Unimplemented because of the same reasons as binding for statements.<br> <b>Note</b>: The driver does not check whether the type of the appended value is compatible with the type of the collection items.</td>
190+
<td rowspan="2">Unimplemented because of the same reasons as binding for statements.<br> <b>Note</b>: The driver does not check whether the type of the appended value is compatible with the type of the collection items.</td>
194191
</tr>
195192
<tr>
196193
<td>cass_collection_append_decimal</td>
197194
</tr>
198-
<tr>
199-
<td>cass_collection_append_duration</td>
200-
</tr>
201195
<tr>
202196
<td colspan=2 align="center" style="font-weight:bold">User Defined Type</td>
203197
</tr>
204198
<tr>
205199
<td>cass_user_type_set_custom[by_name]</td>
206-
<td rowspan="3">Unimplemented because of the same reasons as binding for statements.<br> <b>Note</b>: The driver does not check whether the type of the value being set for a field of the UDT is compatible with the field's actual type.</td>
200+
<td rowspan="2">Unimplemented because of the same reasons as binding for statements.<br> <b>Note</b>: The driver does not check whether the type of the value being set for a field of the UDT is compatible with the field's actual type.</td>
207201
</tr>
208202
<tr>
209203
<td>cass_user_type_set_decimal[by_name]</td>
210204
</tr>
211-
<tr>
212-
<td>cass_user_type_set_duration[by_name]</td>
213-
</tr>
214205
<tr>
215206
<td colspan=2 align="center" style="font-weight:bold">Value</td>
216207
</tr>
217-
<tr>
218-
<td>cass_value_is_duration</td>
219-
<td>Unimplemented</td>
220-
</tr>
221208
<tr>
222209
<td>cass_value_get_decimal</td>
223-
<td rowspan="2">Getting raw bytes of Decimal and Duration values requires lazy deserialization feature in the Rust driver.</td>
224-
</tr>
225-
<tr>
226-
<td>cass_value_get_duration</td>
210+
<td>Getting raw bytes of Decimal values requires lazy deserialization feature in the Rust driver.</td>
227211
</tr>
228212
<tr>
229213
<td>cass_value_get_bytes</td>

scylla-rust-wrapper/src/binding.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,8 @@ macro_rules! make_appender {
137137
}
138138

139139
// TODO: Types for which binding is not implemented yet:
140-
// custom - Not implemented in Rust driver?
140+
// custom - Not implemented in Rust driver
141141
// decimal
142-
// duration - DURATION not implemented in Rust Driver
143142

144143
macro_rules! invoke_binder_maker_macro_with_type {
145144
(null, $macro_name:ident, $this:ty, $consume_v:expr, $fn:ident) => {
@@ -277,6 +276,21 @@ macro_rules! invoke_binder_maker_macro_with_type {
277276
[v @ crate::inet::CassInet]
278277
);
279278
};
279+
(duration, $macro_name:ident, $this:ty, $consume_v:expr, $fn:ident) => {
280+
$macro_name!(
281+
$this,
282+
$consume_v,
283+
$fn,
284+
|m, d, n| {
285+
Ok(Some(Duration(scylla::frame::value::CqlDuration {
286+
months: m,
287+
days: d,
288+
nanoseconds: n
289+
})))
290+
},
291+
[m @ cass_int32_t, d @ cass_int32_t, n @ cass_int64_t]
292+
);
293+
};
280294
(collection, $macro_name:ident, $this:ty, $consume_v:expr, $fn:ident) => {
281295
$macro_name!(
282296
$this,

scylla-rust-wrapper/src/collection.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ make_binders!(string_n, cass_collection_append_string_n);
8888
make_binders!(bytes, cass_collection_append_bytes);
8989
make_binders!(uuid, cass_collection_append_uuid);
9090
make_binders!(inet, cass_collection_append_inet);
91+
make_binders!(duration, cass_collection_append_duration);
9192
make_binders!(collection, cass_collection_append_collection);
9293
make_binders!(tuple, cass_collection_append_tuple);
9394
make_binders!(user_type, cass_collection_append_user_type);

scylla-rust-wrapper/src/query_result.rs

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -915,12 +915,21 @@ pub unsafe extern "C" fn cass_value_data_type(value: *const CassValue) -> *const
915915
Arc::as_ptr(&value_from_raw.value_type)
916916
}
917917

918+
macro_rules! val_ptr_to_ref_ensure_non_null {
919+
($ptr:ident) => {{
920+
if $ptr.is_null() {
921+
return CassError::CASS_ERROR_LIB_NULL_VALUE;
922+
}
923+
ptr_to_ref($ptr)
924+
}};
925+
}
926+
918927
#[no_mangle]
919928
pub unsafe extern "C" fn cass_value_get_float(
920929
value: *const CassValue,
921930
output: *mut cass_float_t,
922931
) -> CassError {
923-
let val: &CassValue = ptr_to_ref(value);
932+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
924933
match val.value {
925934
Some(Value::RegularValue(CqlValue::Float(f))) => std::ptr::write(output, f),
926935
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -935,7 +944,7 @@ pub unsafe extern "C" fn cass_value_get_double(
935944
value: *const CassValue,
936945
output: *mut cass_double_t,
937946
) -> CassError {
938-
let val: &CassValue = ptr_to_ref(value);
947+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
939948
match val.value {
940949
Some(Value::RegularValue(CqlValue::Double(d))) => std::ptr::write(output, d),
941950
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -950,7 +959,7 @@ pub unsafe extern "C" fn cass_value_get_bool(
950959
value: *const CassValue,
951960
output: *mut cass_bool_t,
952961
) -> CassError {
953-
let val: &CassValue = ptr_to_ref(value);
962+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
954963
match val.value {
955964
Some(Value::RegularValue(CqlValue::Boolean(b))) => {
956965
std::ptr::write(output, b as cass_bool_t)
@@ -967,7 +976,7 @@ pub unsafe extern "C" fn cass_value_get_int8(
967976
value: *const CassValue,
968977
output: *mut cass_int8_t,
969978
) -> CassError {
970-
let val: &CassValue = ptr_to_ref(value);
979+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
971980
match val.value {
972981
Some(Value::RegularValue(CqlValue::TinyInt(i))) => std::ptr::write(output, i),
973982
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -982,7 +991,7 @@ pub unsafe extern "C" fn cass_value_get_int16(
982991
value: *const CassValue,
983992
output: *mut cass_int16_t,
984993
) -> CassError {
985-
let val: &CassValue = ptr_to_ref(value);
994+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
986995
match val.value {
987996
Some(Value::RegularValue(CqlValue::SmallInt(i))) => std::ptr::write(output, i),
988997
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -997,7 +1006,7 @@ pub unsafe extern "C" fn cass_value_get_uint32(
9971006
value: *const CassValue,
9981007
output: *mut cass_uint32_t,
9991008
) -> CassError {
1000-
let val: &CassValue = ptr_to_ref(value);
1009+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10011010
match val.value {
10021011
Some(Value::RegularValue(CqlValue::Date(u))) => std::ptr::write(output, u.0), // FIXME: hack
10031012
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -1012,7 +1021,7 @@ pub unsafe extern "C" fn cass_value_get_int32(
10121021
value: *const CassValue,
10131022
output: *mut cass_int32_t,
10141023
) -> CassError {
1015-
let val: &CassValue = ptr_to_ref(value);
1024+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10161025
match val.value {
10171026
Some(Value::RegularValue(CqlValue::Int(i))) => std::ptr::write(output, i),
10181027
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -1027,7 +1036,7 @@ pub unsafe extern "C" fn cass_value_get_int64(
10271036
value: *const CassValue,
10281037
output: *mut cass_int64_t,
10291038
) -> CassError {
1030-
let val: &CassValue = ptr_to_ref(value);
1039+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10311040
match val.value {
10321041
Some(Value::RegularValue(CqlValue::BigInt(i))) => std::ptr::write(output, i),
10331042
Some(Value::RegularValue(CqlValue::Counter(i))) => {
@@ -1049,7 +1058,7 @@ pub unsafe extern "C" fn cass_value_get_uuid(
10491058
value: *const CassValue,
10501059
output: *mut CassUuid,
10511060
) -> CassError {
1052-
let val: &CassValue = ptr_to_ref(value);
1061+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10531062
match val.value {
10541063
Some(Value::RegularValue(CqlValue::Uuid(uuid))) => std::ptr::write(output, uuid.into()),
10551064
Some(Value::RegularValue(CqlValue::Timeuuid(uuid))) => {
@@ -1067,7 +1076,7 @@ pub unsafe extern "C" fn cass_value_get_inet(
10671076
value: *const CassValue,
10681077
output: *mut CassInet,
10691078
) -> CassError {
1070-
let val: &CassValue = ptr_to_ref(value);
1079+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10711080
match val.value {
10721081
Some(Value::RegularValue(CqlValue::Inet(inet))) => std::ptr::write(output, inet.into()),
10731082
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
@@ -1083,7 +1092,7 @@ pub unsafe extern "C" fn cass_value_get_string(
10831092
output: *mut *const c_char,
10841093
output_size: *mut size_t,
10851094
) -> CassError {
1086-
let val: &CassValue = ptr_to_ref(value);
1095+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
10871096
match &val.value {
10881097
// It seems that cpp driver doesn't check the type - you can call _get_string
10891098
// on any type and get internal represenation. I don't see how to do it easily in
@@ -1102,17 +1111,35 @@ pub unsafe extern "C" fn cass_value_get_string(
11021111
CassError::CASS_OK
11031112
}
11041113

1114+
#[no_mangle]
1115+
pub unsafe extern "C" fn cass_value_get_duration(
1116+
value: *const CassValue,
1117+
months: *mut cass_int32_t,
1118+
days: *mut cass_int32_t,
1119+
nanos: *mut cass_int64_t,
1120+
) -> CassError {
1121+
let val: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
1122+
1123+
match &val.value {
1124+
Some(Value::RegularValue(CqlValue::Duration(duration))) => {
1125+
std::ptr::write(months, duration.months);
1126+
std::ptr::write(days, duration.days);
1127+
std::ptr::write(nanos, duration.nanoseconds);
1128+
}
1129+
Some(_) => return CassError::CASS_ERROR_LIB_INVALID_VALUE_TYPE,
1130+
None => return CassError::CASS_ERROR_LIB_NULL_VALUE,
1131+
}
1132+
1133+
CassError::CASS_OK
1134+
}
1135+
11051136
#[no_mangle]
11061137
pub unsafe extern "C" fn cass_value_get_bytes(
11071138
value: *const CassValue,
11081139
output: *mut *const cass_byte_t,
11091140
output_size: *mut size_t,
11101141
) -> CassError {
1111-
if value.is_null() {
1112-
return CassError::CASS_ERROR_LIB_NULL_VALUE;
1113-
}
1114-
1115-
let value_from_raw: &CassValue = ptr_to_ref(value);
1142+
let value_from_raw: &CassValue = val_ptr_to_ref_ensure_non_null!(value);
11161143

11171144
// FIXME: This should be implemented for all CQL types
11181145
// Note: currently rust driver does not allow to get raw bytes of the CQL value.
@@ -1138,12 +1165,19 @@ pub unsafe extern "C" fn cass_value_is_null(value: *const CassValue) -> cass_boo
11381165
pub unsafe extern "C" fn cass_value_is_collection(value: *const CassValue) -> cass_bool_t {
11391166
let val = ptr_to_ref(value);
11401167

1141-
match val.value {
1142-
Some(Value::CollectionValue(Collection::List(_))) => true as cass_bool_t,
1143-
Some(Value::CollectionValue(Collection::Set(_))) => true as cass_bool_t,
1144-
Some(Value::CollectionValue(Collection::Map(_))) => true as cass_bool_t,
1145-
_ => false as cass_bool_t,
1146-
}
1168+
matches!(
1169+
val.value_type.get_value_type(),
1170+
CassValueType::CASS_VALUE_TYPE_LIST
1171+
| CassValueType::CASS_VALUE_TYPE_SET
1172+
| CassValueType::CASS_VALUE_TYPE_MAP
1173+
) as cass_bool_t
1174+
}
1175+
1176+
#[no_mangle]
1177+
pub unsafe extern "C" fn cass_value_is_duration(value: *const CassValue) -> cass_bool_t {
1178+
let val = ptr_to_ref(value);
1179+
1180+
(val.value_type.get_value_type() == CassValueType::CASS_VALUE_TYPE_DURATION) as cass_bool_t
11471181
}
11481182

11491183
#[no_mangle]
@@ -1505,26 +1539,12 @@ pub unsafe extern "C" fn cass_value_get_decimal(
15051539
scale: *mut cass_int32_t,
15061540
) -> CassError {
15071541
}
1508-
#[no_mangle]
1509-
pub unsafe extern "C" fn cass_value_get_duration(
1510-
value: *const CassValue,
1511-
months: *mut cass_int32_t,
1512-
days: *mut cass_int32_t,
1513-
nanos: *mut cass_int64_t,
1514-
) -> CassError {
1515-
}
15161542
extern "C" {
15171543
pub fn cass_value_data_type(value: *const CassValue) -> *const CassDataType;
15181544
}
15191545
extern "C" {
15201546
pub fn cass_value_type(value: *const CassValue) -> CassValueType;
15211547
}
1522-
extern "C" {
1523-
pub fn cass_value_is_collection(value: *const CassValue) -> cass_bool_t;
1524-
}
1525-
extern "C" {
1526-
pub fn cass_value_is_duration(value: *const CassValue) -> cass_bool_t;
1527-
}
15281548
extern "C" {
15291549
pub fn cass_value_item_count(collection: *const CassValue) -> size_t;
15301550
}

scylla-rust-wrapper/src/statement.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,12 @@ make_binders!(
462462
cass_statement_bind_inet_by_name,
463463
cass_statement_bind_inet_by_name_n
464464
);
465+
make_binders!(
466+
duration,
467+
cass_statement_bind_duration,
468+
cass_statement_bind_duration_by_name,
469+
cass_statement_bind_duration_by_name_n
470+
);
465471
make_binders!(
466472
collection,
467473
cass_statement_bind_collection,

scylla-rust-wrapper/src/tuple.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ make_binders!(string_n, cass_tuple_set_string_n);
105105
make_binders!(bytes, cass_tuple_set_bytes);
106106
make_binders!(uuid, cass_tuple_set_uuid);
107107
make_binders!(inet, cass_tuple_set_inet);
108+
make_binders!(duration, cass_tuple_set_duration);
108109
make_binders!(collection, cass_tuple_set_collection);
109110
make_binders!(tuple, cass_tuple_set_tuple);
110111
make_binders!(user_type, cass_tuple_set_user_type);

scylla-rust-wrapper/src/user_type.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ make_binders!(
181181
cass_user_type_set_inet_by_name,
182182
cass_user_type_set_inet_by_name_n
183183
);
184+
make_binders!(
185+
duration,
186+
cass_user_type_set_duration,
187+
cass_user_type_set_duration_by_name,
188+
cass_user_type_set_duration_by_name_n
189+
);
184190
make_binders!(
185191
collection,
186192
cass_user_type_set_collection,

scylla-rust-wrapper/src/value.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::{convert::TryInto, net::IpAddr};
22

33
use scylla::{
4-
frame::{response::result::ColumnType, value::CqlDate},
4+
frame::{
5+
response::result::ColumnType,
6+
value::{CqlDate, CqlDuration},
7+
},
58
serialize::{
69
value::{
710
BuiltinSerializationErrorKind, MapSerializationErrorKind, SerializeCql,
@@ -40,6 +43,7 @@ pub enum CassCqlValue {
4043
Uuid(Uuid),
4144
Date(CqlDate),
4245
Inet(IpAddr),
46+
Duration(CqlDuration),
4347
Tuple(Vec<Option<CassCqlValue>>),
4448
List(Vec<CassCqlValue>),
4549
Map(Vec<(CassCqlValue, CassCqlValue)>),
@@ -117,6 +121,9 @@ impl CassCqlValue {
117121
CassCqlValue::Inet(v) => {
118122
<IpAddr as SerializeCql>::serialize(v, &ColumnType::Inet, writer)
119123
}
124+
CassCqlValue::Duration(v) => {
125+
<CqlDuration as SerializeCql>::serialize(v, &ColumnType::Duration, writer)
126+
}
120127
CassCqlValue::Tuple(fields) => serialize_tuple_like(fields.iter(), writer),
121128
CassCqlValue::List(l) => serialize_sequence(l.len(), l.iter(), writer),
122129
CassCqlValue::Map(m) => {

0 commit comments

Comments
 (0)