-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hide public usages of num_bigint::BigInt
behind a feature flag
#902
Conversation
num_bigint::BigInt
behind a feature flag
c1fe677
to
ce846b7
Compare
v2: fixed review comments |
85eb76a
to
eb0acf5
Compare
v3: adjusted |
eb0acf5
to
336d094
Compare
v4: |
336d094
to
fa1ff6f
Compare
v5: fixes based on review comments |
fa1ff6f
to
4cc1b9f
Compare
v6: removed |
4cc1b9f
to
0e07e80
Compare
let table_name = "cql_varint_tests"; | ||
let session: Session = create_new_session_builder().build().await.unwrap(); | ||
let ks = unique_keyspace_name(); | ||
|
||
session | ||
.query( | ||
format!( | ||
"CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = \ | ||
{{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", | ||
ks | ||
), | ||
&[], | ||
) | ||
.await | ||
.unwrap(); | ||
session.use_keyspace(ks, false).await.unwrap(); | ||
|
||
session | ||
.query( | ||
format!( | ||
"CREATE TABLE IF NOT EXISTS {} (id int PRIMARY KEY, val varint)", | ||
table_name | ||
), | ||
&[], | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let prepared_insert = session | ||
.prepare(format!( | ||
"INSERT INTO {} (id, val) VALUES (0, ?)", | ||
table_name | ||
)) | ||
.await | ||
.unwrap(); | ||
let prepared_select = session | ||
.prepare(format!("SELECT val FROM {} WHERE id = 0", table_name)) | ||
.await | ||
.unwrap(); | ||
|
||
for test in tests { | ||
let cql_varint = CqlVarint::from_signed_bytes_be_slice(&test); | ||
session | ||
.execute(&prepared_insert, (&cql_varint,)) | ||
.await | ||
.unwrap(); | ||
|
||
let read_values: Vec<CqlVarint> = session | ||
.execute(&prepared_select, &[]) | ||
.await | ||
.unwrap() | ||
.rows | ||
.unwrap() | ||
.into_typed::<(CqlVarint,)>() | ||
.map(Result::unwrap) | ||
.map(|row| row.0) | ||
.collect::<Vec<_>>(); | ||
|
||
assert_eq!(read_values, vec![cql_varint]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it can't be expressed as a call to run_tests
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As run_tests
requires that the type implements std::str::FromStr
. It's not trivial to implement it without the use of the num_bigint
crate.
CQL accepts varint
string literals represented in decimal/octal. Implementing FromStr
for hexadecimal numbers wouldn't be hard but the hexadecimal strings provided to run_tests
couldn't be contained as literals in queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As
run_tests
requires that the type implementsstd::str::FromStr
. It's not trivial to implement it without the use of thenum_bigint
crate.CQL accepts
varint
string literals represented in decimal/octal. ImplementingFromStr
for hexadecimal numbers wouldn't be hard but the hexadecimal strings provided torun_tests
couldn't be contained as literals in queries.
I don't understand the last sentence. Why couldn't they?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because you can't put a hexadecimal literal for a value of type varint in CQL query:
cqlsh> CREATE TABLE ks.t (a int PRIMARY KEY, b varint);
cqlsh> INSERT INTO ks.t (a, b) VALUES (0, 0x1);
InvalidRequest: Error from server: code=2200 [Invalid query] message="Invalid HEX constant (0x1) for "b" of type varint"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found out that you actually can, with blobAsVarint
built-in CQL function:
cqlsh> create table ks.t (pk int, v varint, primary key (pk));
cqlsh> insert into ks.t (pk, v) values (2, blobasvarint(0x123421934815718293482108421905702184921834021943));
cqlsh> select pk, v from ks.t;
pk | v
----+-----------------------------------------------------------
2 | 446351888295288528376725140517290295205369310673010563395
(1 rows)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps later we can adjust run_tests
to take a list of (Cql?)Values instead of strings, use CqlValueDisplayer
to print them when putting them into the query and finally compare the values fetched from the database.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do it in a separate PR? I can create an issue regarding this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do it in a separate PR?
Yes, that's what I meant by "later".
0e07e80
to
d9e95b0
Compare
v7: added test cases for varints that can't be contained in any primitive type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.
d9e95b0
to
b20e26e
Compare
v8:
|
Now that #894 was merged, there are conflicts with main. Please rebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add steps to the rust.yml
workflow which cargo check
the crate when only num-bigint-03
or num-bigint-04
features are enabled.
scylla-cql/src/frame/value.rs
Outdated
/// As of now, users are guaranteed to fetch the exact same data they inserted | ||
/// previously (even if it was not normalized). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about ScyllaDB's conversion of empty values to null
? I think this behavior makes your statement incorrect.
In general, I'd avoid using statements that refer to "as of now" when they refer to some properties that can become false independently from the documentation (i.e. they don't apply to the property of the library but rather something external like ScyllaDB).
let table_name = "cql_varint_tests"; | ||
let session: Session = create_new_session_builder().build().await.unwrap(); | ||
let ks = unique_keyspace_name(); | ||
|
||
session | ||
.query( | ||
format!( | ||
"CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = \ | ||
{{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", | ||
ks | ||
), | ||
&[], | ||
) | ||
.await | ||
.unwrap(); | ||
session.use_keyspace(ks, false).await.unwrap(); | ||
|
||
session | ||
.query( | ||
format!( | ||
"CREATE TABLE IF NOT EXISTS {} (id int PRIMARY KEY, val varint)", | ||
table_name | ||
), | ||
&[], | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let prepared_insert = session | ||
.prepare(format!( | ||
"INSERT INTO {} (id, val) VALUES (0, ?)", | ||
table_name | ||
)) | ||
.await | ||
.unwrap(); | ||
let prepared_select = session | ||
.prepare(format!("SELECT val FROM {} WHERE id = 0", table_name)) | ||
.await | ||
.unwrap(); | ||
|
||
for test in tests { | ||
let cql_varint = CqlVarint::from_signed_bytes_be_slice(&test); | ||
session | ||
.execute(&prepared_insert, (&cql_varint,)) | ||
.await | ||
.unwrap(); | ||
|
||
let read_values: Vec<CqlVarint> = session | ||
.execute(&prepared_select, &[]) | ||
.await | ||
.unwrap() | ||
.rows | ||
.unwrap() | ||
.into_typed::<(CqlVarint,)>() | ||
.map(Result::unwrap) | ||
.map(|row| row.0) | ||
.collect::<Vec<_>>(); | ||
|
||
assert_eq!(read_values, vec![cql_varint]) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps later we can adjust run_tests
to take a list of (Cql?)Values instead of strings, use CqlValueDisplayer
to print them when putting them into the query and finally compare the values fetched from the database.
b20e26e
to
93c6941
Compare
v9: rebased on top of master so the upcoming diff addressing review comments is clearer |
Added a `CqlVarint` type which represents the native cql varint type. Varint value is represented as a signed binary in big-endian order.
Hidden public usages of the `num_bigint::BigInt` (version 0.3) behind `num-bigint-03` feature flag.
93c6941
to
a7f0787
Compare
v10: addressed review comments |
Added test cases for varints that can't be contained in any primitive.
a7f0787
to
21988eb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
#[test] | ||
fn cql_varint_normalization_with_bigint() { | ||
fn cql_varint_normalization_with_bigint03() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: there is no corresponding test for 0.4
. I just checked that the normalization behavior is the same in 0.4
, fortunately. The test case can be added in a follow-up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I've also checked that normalization works the same in this case. Wasn't sure if such test case is redundant or not.
Related issue: #771 (not fixed yet, as
bigdecimal::BigDecimal
is an unstable type as well).Fixes: #679
Changes:
CqlVarint
type which is a simple native representation of cqlvarint
typeCqlVarint
withCqlValue::Varint
num_bigint
- v0.3 and v0.4) behind feature flags. Notice, however, thatnum_bigint v0.3
is still used within driver's code even without any feature flags. We make use of some library utilities such as pretty printing, or normalization of value's binary representation (e.g. getting rid of leading zeros).Pre-review checklist
./docs/source/
.Fixes:
annotations to PR description.