Skip to content

transport: Implement SCYLLA_USE_METADATA_ID support#23292

Merged
scylladb-promoter merged 3 commits intoscylladb:masterfrom
andrzej-jackowski-scylladb:metadata-id-support
May 29, 2025
Merged

transport: Implement SCYLLA_USE_METADATA_ID support#23292
scylladb-promoter merged 3 commits intoscylladb:masterfrom
andrzej-jackowski-scylladb:metadata-id-support

Conversation

@andrzej-jackowski-scylladb
Copy link
Contributor

@andrzej-jackowski-scylladb andrzej-jackowski-scylladb commented Mar 14, 2025

Metadata id was introduced in CQLv5 to make metadata of prepared
statement metadata consistent between driver and database.
This commit introduces a protocol extension that allows to use the same
mechanism in CQLv4. As CQLv5 is currently unsupported in ScyllaDb (as well
as in some of the drivers), the motivation is to allow fixing #20860.

This change:
- Implement metadata::calculate_metadata_id()
- Implement SCYLLA_USE_METADATA_ID protocol extension for CQLv4
- Added description of SCYLLA_USE_METADATA_ID in documentation
- Add boost tests to confirm correctness of the function
- Add python tests for table metadata change corner-cases

Fixes #20860

Also see related https://scylladb.atlassian.net/wiki/spaces/RND/pages/42238631/MetadataId+extension+in+CQLv4+Requirement+Document

No backport needed (unless specifically requested by a customer), because there are existing workarounds for the issue

@andrzej-jackowski-scylladb andrzej-jackowski-scylladb added the backport/none Backport is not required label Mar 14, 2025
@mykaul
Copy link
Contributor

mykaul commented Mar 14, 2025

Closes #20860

I believe we use 'Fixes:' - unsure if it matters much.

@avikivity
Copy link
Member

Closes #20860

I believe we use 'Fixes:' - unsure if it matters much.

Yes the automation relies on it.

@scylladb-promoter
Copy link
Contributor

🔴 CI State: FAILURE

✅ - Build
✅ - Unit Tests Custom
The following new/updated tests ran 100 times for each mode:
🔹 boost/metadata_id_test
🔹 cluster/test_metadata_id
✅ - dtest with tablets
✅ - dtest with consistent topology changes
✅ - dtest with gossip topology changes
❌ - Unit Tests

Build Details:

  • Duration: 10 hr
  • Builder: spider6.cloudius-systems.com

@andrzej-jackowski-scylladb
Copy link
Contributor Author

Closes #20860

I believe we use 'Fixes:' - unsure if it matters much.

Yes the automation relies on it.

@avikivity, I need a clarification. I can see so many commits that use "Closes" instead of "Fixes", for instance this one: a72dde2

I can start using "Fixes" instead "Closes" but currently I'm lost what is the proper, up to date rule how to use "Closes" and "Fixes". Especially, some of the commits use both (e.g. c082184)

@mykaul
Copy link
Contributor

mykaul commented Mar 17, 2025

Closes #20860

I believe we use 'Fixes:' - unsure if it matters much.

Yes the automation relies on it.

@avikivity, I need a clarification. I can see so many commits that use "Closes" instead of "Fixes", for instance this one: a72dde2

I can start using "Fixes" instead "Closes" but currently I'm lost what is the proper, up to date rule how to use "Closes" and "Fixes". Especially, some of the commits use both (e.g. c082184)

Look at the PR - #22462 - it 'fixes'. The merge commit closes the PR.

@avikivity
Copy link
Member

Closes #20860

I believe we use 'Fixes:' - unsure if it matters much.

Yes the automation relies on it.

@avikivity, I need a clarification. I can see so many commits that use "Closes" instead of "Fixes", for instance this one: a72dde2

I can start using "Fixes" instead "Closes" but currently I'm lost what is the proper, up to date rule how to use "Closes" and "Fixes". Especially, some of the commits use both (e.g. c082184)

That's a side effect of github inflexibility. We base pull request on master but commit to next, and github doesn't allow that from the UI. So we have a script scripts/pull_github_pr.sh to do that for us. It uses Closes to mark the pull request closed.

So we have: Fixes - for marking an issue fixed, Closes - for marking a pull request closed. Having the separation prevents chasing the wrong number.

CQLv5 introduced metadata_id, which is a checksum computed from column
names and types, to track schema changes in prepared statements. This
commit introduces calculate_metadata_id to compute such id for given
metadata.

Please note that calculate_metadata_id() produces different hashes
than Cassandra's computeResultMetadataId(). We use SHA256 truncated to
128 bits instead of MD5. There are also two smaller technical
differences: calculate_metadata_id() doesn't add unneeded zeros and it
adds a length of a string when an sstring is being fed to the hasher.
The difference is intentional because MD5 has known vulnerabilities,
moreover we don't want to introduce any dependency between our
metadata_id and Cassandra's.

This change:
 - Add cql_metadata_id_type
 - Implement metadata::calculate_metadata_id()
 - Add boost tests to confirm correctness of the function
Metadata id was introduced in CQLv5 to make metadata of prepared
statement consistent between driver and database. This commit introduces
a protocol extension that allows to use the same mechanism in CQLv4.

This change:
 - Introduce SCYLLA_USE_METADATA_ID protocol extension for CQLv4
 - Introduce METADATA_CHANGED flag in RESULT. The flag cames directly
   from CQLv5 binary protocol. In CQLv4, the bit was never used, so we
   assume it is safe to reuse it.
 - Implement handling of metadata_id and METADATA_CHANGED in RESULT rows
 - Implement returning metadata_id in RESULT prepared
 - Implement reading metadata_id from EXECUTE
 - Added description of SCYLLA_USE_METADATA_ID in documentation

Metadata_id is wrapped in cql_metadata_id_wrapper because we need to
distinguish the following situations:
 - Metadata_id is not supported by the protocol (e.g. CQLv4 without the
   extension is used)
 - Metadata_id is supported by the protocol but not set - e.g. PREPARE
   query is being handled: it doesn't contain metadata_id in the
   request but the reply (RESULT prepared) must contain metadata_id
 - Metadata_id is supported by the protocol and set, any number of
   bytes >= 0 is allowed, according to the CQLv5 protocol specification

Fixes scylladb#20860
Implement corner-cases of prepared statement metadata, as described in
scylladb#20860.

Although the purpose of the test was to verify the newly implemented
SCYLLA_USE_METADATA_ID protocol extension, the test also passes with
scylla-driver 3.29.3 that doesn't implement the support for this
extension. That is because the driver doesn't implement support for
skip_metadata flag, so fresh metadata are included in every prepared
statement response, regardless of the metadata_id.

This change:
 - Add test_changed_prepared_statement_metadata_columns to verify
   a scenario when a number of columns changes in a table used by a
   prepared statement
 - Add test_changed_prepared_statement_metadata_types to verify
   a scenario when a type of a column changes in a table used by a
   prepared statement
 - Add test_changed_prepared_statement_metadata_udt to veriy
   a scenario when a UDT changes in a table used by a prepared statement

I tested the code with a modified Python driver
(ref. scylladb/python-driver#457):
 - If SKIP_METADATA is enabled (scylladb/python-driver@c1809c1)
   but not other changes are introduced, all three test cases fail.
 - If SKIP_METADATA is disabled (no scylladb/python-driver@c1809c1) all
   test cases pass because fresh metadata are included in each reply.
 - If SKIP_METADATA is enabled (scylladb/python-driver@c1809c1)
   and SCYLLA_USE_METADATA_ID extension is included
   (scylladb/python-driver@8aba164) all test cases pass and verifies
   the correctness the implementation.
@andrzej-jackowski-scylladb
Copy link
Contributor Author

andrzej-jackowski-scylladb commented May 14, 2025

v13:

  • Rebase

v14:

  • Remove unused import
  • Changed mutable std::optional<cql_metadata_id_type> _cached_metadata_id to cql_metadata_id_type
  • Removed _supported_by_protocol

@scylladb-promoter
Copy link
Contributor

🟢 CI State: SUCCESS

✅ - Framework test
✅ - Build
✅ - Unit Tests Custom
The following new/updated tests ran 100 times for each mode:
🔹 boost/schema_change_test
🔹 cluster/test_metadata_id
✅ - dtest with tablets
✅ - dtest with gossip topology changes
✅ - dtest with consistent topology changes
✅ - Unit Tests

Build Details:

  • Duration: 7 hr 22 min
  • Builder: spider1.cloudius-systems.com

@andrzej-jackowski-scylladb andrzej-jackowski-scylladb added the status/merge_candidate Item needs a maintainer's assistance in merging label May 16, 2025
@andrzej-jackowski-scylladb
Copy link
Contributor Author

@scylladb/scylla-maint please consider merging

@andrzej-jackowski-scylladb
Copy link
Contributor Author

@scylladb/scylla-maint all recent Dmitry's comments are resolved. Please consider merging.

@scylladb-promoter scylladb-promoter merged commit c00824c into scylladb:master May 29, 2025
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/none Backport is not required promoted-to-master status/merge_candidate Item needs a maintainer's assistance in merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prepared statement invalidation loopholes

10 participants

Comments