Skip to main content

systemprompt_database/models/
query.rs

1//! Query primitives: selectors and dynamic results.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Copy)]
11pub struct DatabaseQuery {
12    postgres: &'static str,
13}
14
15impl DatabaseQuery {
16    #[must_use]
17    pub const fn new(query: &'static str) -> Self {
18        Self { postgres: query }
19    }
20
21    #[must_use]
22    pub const fn postgres(&self) -> &str {
23        self.postgres
24    }
25}
26
27pub trait QuerySelector: Sync {
28    fn select_query(&self) -> &str;
29}
30
31impl QuerySelector for &str {
32    fn select_query(&self) -> &str {
33        self
34    }
35}
36
37impl QuerySelector for String {
38    fn select_query(&self) -> &str {
39        self.as_str()
40    }
41}
42
43impl QuerySelector for DatabaseQuery {
44    fn select_query(&self) -> &str {
45        self.postgres()
46    }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct QueryResult {
51    pub columns: Vec<String>,
52    pub rows: Vec<QueryRow>,
53    pub row_count: usize,
54    pub execution_time_ms: u64,
55}
56
57pub type QueryRow = HashMap<String, Value>;
58
59impl QueryResult {
60    #[must_use]
61    pub const fn new() -> Self {
62        Self {
63            columns: vec![],
64            rows: vec![],
65            row_count: 0,
66            execution_time_ms: 0,
67        }
68    }
69
70    #[must_use]
71    pub const fn is_empty(&self) -> bool {
72        self.rows.is_empty()
73    }
74
75    #[must_use]
76    pub fn first(&self) -> Option<&QueryRow> {
77        self.rows.first()
78    }
79}
80
81impl Default for QueryResult {
82    fn default() -> Self {
83        Self::new()
84    }
85}