use std::{
fmt,
sync::atomic::{AtomicU64, Ordering},
time::{SystemTime, UNIX_EPOCH},
};
use serde::{Deserialize, Serialize};
use crate::plan::NodeId;
static NEXT_QUERY_SEQUENCE: AtomicU64 = AtomicU64::new(1);
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(transparent)]
pub struct QueryId(String);
impl QueryId {
pub const UNASSIGNED: &'static str = "unassigned";
pub fn mint() -> Self {
let sequence = NEXT_QUERY_SEQUENCE.fetch_add(1, Ordering::Relaxed);
let nanos = SystemTime::now().duration_since(UNIX_EPOCH).map_or(0, |duration| duration.as_nanos() as u64);
Self(format!("q-{nanos:016x}-{sequence:08x}"))
}
pub fn new(value: impl Into<String>) -> Self {
let value = value.into();
if value.trim().is_empty() { Self::default() } else { Self(value) }
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn is_assigned(&self) -> bool {
self.0 != Self::UNASSIGNED
}
}
impl Default for QueryId {
fn default() -> Self {
Self(Self::UNASSIGNED.to_string())
}
}
impl From<String> for QueryId {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl From<&str> for QueryId {
fn from(value: &str) -> Self {
Self::new(value)
}
}
impl From<&String> for QueryId {
fn from(value: &String) -> Self {
Self::new(value.clone())
}
}
impl fmt::Display for QueryId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for QueryId {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where D: serde::Deserializer<'de> {
String::deserialize(deserializer).map(Self::new)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct TraceId(String);
impl TraceId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for TraceId {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl From<&str> for TraceId {
fn from(value: &str) -> Self {
Self::new(value)
}
}
impl fmt::Display for TraceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PlanNodeId(String);
impl PlanNodeId {
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<NodeId> for PlanNodeId {
fn from(value: NodeId) -> Self {
Self(value.to_string())
}
}
impl From<String> for PlanNodeId {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl From<&str> for PlanNodeId {
fn from(value: &str) -> Self {
Self::new(value)
}
}
impl fmt::Display for PlanNodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CompiledTaskId(String);
impl CompiledTaskId {
pub fn new(value: impl ToString) -> Self {
Self(value.to_string())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for CompiledTaskId {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl From<&str> for CompiledTaskId {
fn from(value: &str) -> Self {
Self::new(value)
}
}
impl fmt::Display for CompiledTaskId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}