Skip to main content

icydb_core/db/query/fingerprint/
fingerprint.rs

1//! Module: query::fingerprint::fingerprint
2//! Responsibility: deterministic plan fingerprint derivation from planner contracts.
3//! Does not own: explain projection assembly or execution-plan compilation.
4//! Boundary: stable plan identity hash surface for diagnostics/caching.
5
6use crate::db::{
7    codec::cursor::encode_cursor,
8    query::plan::AccessPlannedQuery,
9    query::{
10        explain::ExplainPlan,
11        fingerprint::{finalize_sha256_digest, hash_parts, new_plan_fingerprint_hasher_v2},
12    },
13};
14
15///
16/// PlanFingerprint
17///
18/// Stable, deterministic fingerprint for logical plans.
19///
20
21#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
22pub struct PlanFingerprint([u8; 32]);
23
24impl PlanFingerprint {
25    #[must_use]
26    pub fn as_hex(&self) -> String {
27        encode_cursor(&self.0)
28    }
29}
30
31impl std::fmt::Display for PlanFingerprint {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.write_str(&self.as_hex())
34    }
35}
36
37impl AccessPlannedQuery {
38    /// Compute a stable fingerprint for this logical plan.
39    #[must_use]
40    pub(in crate::db) fn fingerprint(&self) -> PlanFingerprint {
41        let projection = self.projection_spec_for_identity();
42        let mut hasher = new_plan_fingerprint_hasher_v2();
43        hash_parts::hash_planned_query_profile_with_projection(
44            &mut hasher,
45            self,
46            hash_parts::ExplainHashProfile::FingerprintV2,
47            &projection,
48        );
49
50        PlanFingerprint(finalize_sha256_digest(hasher))
51    }
52}
53
54impl ExplainPlan {
55    /// Compute a stable fingerprint for this explain plan.
56    #[must_use]
57    pub fn fingerprint(&self) -> PlanFingerprint {
58        // Phase 1: hash canonical explain fields under the current fingerprint profile.
59        let mut hasher = new_plan_fingerprint_hasher_v2();
60        hash_parts::hash_explain_plan_profile(
61            &mut hasher,
62            self,
63            hash_parts::ExplainHashProfile::FingerprintV2,
64        );
65
66        // Phase 2: finalize into the fixed-width fingerprint payload.
67        PlanFingerprint(finalize_sha256_digest(hasher))
68    }
69}