axum_sql_viewer/
schema.rs

1//! Schema types for dynamic database introspection
2//!
3//! These types represent database schema information discovered at runtime.
4
5use serde::{Deserialize, Serialize};
6
7/// Complete schema information for a database table
8#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct TableSchema {
11    /// Name of the table
12    pub name: String,
13
14    /// List of columns in the table
15    pub columns: Vec<ColumnInfo>,
16
17    /// Primary key column names (if any)
18    pub primary_key: Option<Vec<String>>,
19
20    /// Foreign key constraints
21    pub foreign_keys: Vec<ForeignKey>,
22
23    /// Index definitions
24    pub indexes: Vec<IndexInfo>,
25}
26
27/// Information about a single column
28#[derive(Debug, Clone, Serialize, Deserialize)]
29#[serde(rename_all = "camelCase")]
30pub struct ColumnInfo {
31    /// Column name
32    pub name: String,
33
34    /// SQL data type (e.g., "INTEGER", "TEXT", "VARCHAR(255)")
35    pub data_type: String,
36
37    /// Whether the column allows NULL values
38    pub nullable: bool,
39
40    /// Default value expression (if any)
41    pub default_value: Option<String>,
42
43    /// Whether this column is part of the primary key
44    pub is_primary_key: bool,
45}
46
47/// Foreign key constraint information
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct ForeignKey {
51    /// Column name in this table
52    pub column: String,
53
54    /// Referenced table name
55    pub references_table: String,
56
57    /// Referenced column name
58    pub references_column: String,
59}
60
61/// Index information
62#[derive(Debug, Clone, Serialize, Deserialize)]
63#[serde(rename_all = "camelCase")]
64pub struct IndexInfo {
65    /// Index name
66    pub name: String,
67
68    /// Columns included in the index
69    pub columns: Vec<String>,
70
71    /// Whether the index enforces uniqueness
72    pub unique: bool,
73}
74
75/// Information about a table (for listing)
76#[derive(Debug, Clone, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78pub struct TableInfo {
79    /// Table name
80    pub name: String,
81
82    /// Approximate row count (if available)
83    pub row_count: Option<u64>,
84}
85
86/// Query parameters for fetching rows
87#[derive(Debug, Clone, Deserialize)]
88#[serde(rename_all = "camelCase")]
89pub struct RowQuery {
90    /// Starting offset for pagination
91    #[serde(default)]
92    pub offset: u64,
93
94    /// Maximum number of rows to return
95    #[serde(default = "default_limit")]
96    pub limit: u64,
97
98    /// Column name to sort by
99    pub sort_by: Option<String>,
100
101    /// Sort order
102    pub sort_order: Option<SortOrder>,
103
104    /// Column filters (column_name -> filter_value)
105    #[serde(default)]
106    pub filters: std::collections::HashMap<String, String>,
107}
108
109fn default_limit() -> u64 {
110    100
111}
112
113/// Sort order for row queries
114#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
115#[serde(rename_all = "camelCase")]
116pub enum SortOrder {
117    Ascending,
118    Descending,
119}
120
121/// Response containing table rows
122#[derive(Debug, Clone, Serialize, Deserialize)]
123#[serde(rename_all = "camelCase")]
124pub struct RowsResponse {
125    /// The rows returned
126    pub rows: Vec<serde_json::Value>,
127
128    /// Column names in the result
129    pub columns: Vec<String>,
130
131    /// Total number of rows in the table (with filters applied)
132    pub total: u64,
133
134    /// Current offset
135    pub offset: u64,
136
137    /// Limit used for this query
138    pub limit: u64,
139
140    /// Whether there are more rows available
141    pub has_more: bool,
142}
143
144/// Response from listing tables
145#[derive(Debug, Clone, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct TablesResponse {
148    /// List of tables
149    pub tables: Vec<TableInfo>,
150}
151
152/// Request to execute a raw SQL query
153#[derive(Debug, Clone, Deserialize)]
154#[serde(rename_all = "camelCase")]
155pub struct QueryRequest {
156    /// SQL query to execute
157    pub sql: String,
158}
159
160/// Result from executing a query
161#[derive(Debug, Clone, Serialize, Deserialize)]
162#[serde(rename_all = "camelCase")]
163pub struct QueryResult {
164    /// Column names in the result
165    pub columns: Vec<String>,
166
167    /// Rows returned (empty for non-SELECT queries)
168    pub rows: Vec<serde_json::Value>,
169
170    /// Number of rows affected (for INSERT/UPDATE/DELETE)
171    pub affected_rows: u64,
172
173    /// Query execution time in milliseconds
174    pub execution_time_milliseconds: u64,
175
176    /// Error message if the query failed
177    pub error: Option<String>,
178}
179
180/// Response for row count queries
181#[derive(Debug, Clone, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub struct CountResponse {
184    /// Total number of rows
185    pub count: u64,
186}