Skip to content
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

Merged
merged 14 commits into from
Jan 26, 2024

Conversation

muzarski
Copy link
Contributor

@muzarski muzarski commented Jan 3, 2024

Related issue: #771 (not fixed yet, as bigdecimal::BigDecimal is an unstable type as well).

Fixes: #679

Changes:

  • added CqlVarint type which is a simple native representation of cql varint type
  • wrapped CqlVarint with CqlValue::Varint
  • hidden public usages of unstable types (num_bigint - v0.3 and v0.4) behind feature flags. Notice, however, that num_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

  • I have split my patch into logically separate commits.
  • All commit messages clearly explain what they change and why.
  • I added relevant tests for new features and bug fixes.
  • All commits compile, pass static checks and pass test.
  • PR description sums up the changes and reasons why they should be introduced.
  • I have provided docstrings for the public items that I want to introduce.
  • I have adjusted the documentation in ./docs/source/.
  • I added appropriate Fixes: annotations to PR description.

@muzarski muzarski changed the title Num bigint as feature Hide public usages of num_bigint::BigInt behind a feature flag Jan 3, 2024
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/response/cql_to_rust.rs Outdated Show resolved Hide resolved
scylla/src/utils/pretty.rs Outdated Show resolved Hide resolved
scylla-cql/Cargo.toml Outdated Show resolved Hide resolved
scylla-cql/src/frame/response/result.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value_tests.rs Outdated Show resolved Hide resolved
scylla/src/transport/cql_types_test.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
@muzarski muzarski force-pushed the num-bigint-as-feature branch from c1fe677 to ce846b7 Compare January 11, 2024 16:46
@muzarski
Copy link
Contributor Author

v2: fixed review comments

@muzarski muzarski force-pushed the num-bigint-as-feature branch from 85eb76a to eb0acf5 Compare January 12, 2024 10:46
@muzarski
Copy link
Contributor Author

v3: adjusted Cargo.lock.msrv file.

@muzarski muzarski requested a review from piodul January 12, 2024 10:52
@muzarski muzarski force-pushed the num-bigint-as-feature branch from eb0acf5 to 336d094 Compare January 12, 2024 11:25
@muzarski
Copy link
Contributor Author

v4:
implemented From<Vec<u8>> for CqlVarint and From<CqlVarint> for Vec<u8>

scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla/src/transport/cql_types_test.rs Outdated Show resolved Hide resolved
scylla/Cargo.toml Outdated Show resolved Hide resolved
@muzarski muzarski force-pushed the num-bigint-as-feature branch from 336d094 to fa1ff6f Compare January 12, 2024 13:49
@muzarski muzarski requested a review from piodul January 12, 2024 13:51
@muzarski
Copy link
Contributor Author

v5: fixes based on review comments

@muzarski muzarski force-pushed the num-bigint-as-feature branch from fa1ff6f to 4cc1b9f Compare January 12, 2024 14:06
@muzarski
Copy link
Contributor Author

v6: removed derive(Eq) from CqlVarint type

@muzarski muzarski force-pushed the num-bigint-as-feature branch from 4cc1b9f to 0e07e80 Compare January 12, 2024 15:15
@avelanarius avelanarius added this to the 0.12.0 milestone Jan 15, 2024
scylla/src/transport/cql_types_test.rs Show resolved Hide resolved
Comment on lines +156 to +218
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])
}
Copy link
Collaborator

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?

Copy link
Contributor Author

@muzarski muzarski Jan 18, 2024

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.

Copy link
Collaborator

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.

I don't understand the last sentence. Why couldn't they?

Copy link
Contributor Author

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"

Copy link
Collaborator

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)

Copy link
Collaborator

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.

Copy link
Contributor Author

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.

Copy link
Collaborator

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".

scylla/Cargo.toml Show resolved Hide resolved
@muzarski muzarski force-pushed the num-bigint-as-feature branch from 0e07e80 to d9e95b0 Compare January 19, 2024 04:02
@muzarski
Copy link
Contributor Author

v7: added test cases for varints that can't be contained in any primitive type

@muzarski muzarski requested a review from Lorak-mmk January 19, 2024 05:56
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla/Cargo.toml Show resolved Hide resolved
Copy link
Collaborator

@Lorak-mmk Lorak-mmk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

scylla/src/utils/pretty.rs Outdated Show resolved Hide resolved
@muzarski muzarski force-pushed the num-bigint-as-feature branch from d9e95b0 to b20e26e Compare January 25, 2024 15:55
@muzarski
Copy link
Contributor Author

v8:

  • adjusted CqlValueDisplayer for CqlVarint
  • removed normalization during CqlVarint initialization. Now, normalization is performed during comparison. To compare two CqlVarint values, we compare their normalized sublices
  • restored docstring comments about database format of varint values - including information about non-normalized values
  • added docstrings for comparison logic

@muzarski muzarski requested review from Lorak-mmk and piodul January 25, 2024 15:58
@piodul
Copy link
Collaborator

piodul commented Jan 26, 2024

Now that #894 was merged, there are conflicts with main. Please rebase.

Copy link
Collaborator

@piodul piodul left a 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.

Comment on lines 65 to 229
/// As of now, users are guaranteed to fetch the exact same data they inserted
/// previously (even if it was not normalized).
Copy link
Collaborator

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

scylla-cql/src/frame/value.rs Show resolved Hide resolved
scylla-cql/src/frame/value.rs Show resolved Hide resolved
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value.rs Outdated Show resolved Hide resolved
scylla-cql/src/frame/value_tests.rs Show resolved Hide resolved
Comment on lines +156 to +218
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])
}
Copy link
Collaborator

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.

@muzarski muzarski force-pushed the num-bigint-as-feature branch from b20e26e to 93c6941 Compare January 26, 2024 11:08
@muzarski
Copy link
Contributor Author

v9: rebased on top of master so the upcoming diff addressing review comments is clearer

@muzarski muzarski force-pushed the num-bigint-as-feature branch from 93c6941 to a7f0787 Compare January 26, 2024 12:23
@muzarski
Copy link
Contributor Author

v10: addressed review comments

@muzarski muzarski force-pushed the num-bigint-as-feature branch from a7f0787 to 21988eb Compare January 26, 2024 12:29
@muzarski muzarski requested a review from piodul January 26, 2024 12:44
Copy link
Collaborator

@piodul piodul left a 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() {
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

@Lorak-mmk Lorak-mmk merged commit 9a84387 into scylladb:main Jan 26, 2024
9 checks passed
@Lorak-mmk Lorak-mmk mentioned this pull request Feb 1, 2024
@muzarski muzarski deleted the num-bigint-as-feature branch October 29, 2024 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

num_bigint::BigInt: Value is not satisfied error when compiling varint example from docs
4 participants