Skip to main content

sqlitegraph_cli/
cli.rs

1use clap::{Parser, Subcommand, ValueEnum};
2use std::path::PathBuf;
3
4#[derive(Clone, Debug, ValueEnum, Default)]
5pub enum BackendType {
6    #[default]
7    Sqlite,
8    #[cfg(feature = "native-v3")]
9    V3,
10}
11
12#[derive(Parser)]
13#[command(name = "sqlitegraph")]
14#[command(about = "SQLiteGraph CLI - Graph database query tool")]
15#[command(version)]
16pub struct Cli {
17    /// Database file path
18    #[arg(short, long, default_value = "graph.db")]
19    pub db: PathBuf,
20
21    /// Backend type
22    #[arg(short, long, value_enum, default_value = "sqlite")]
23    pub backend: BackendType,
24
25    /// Allow write operations (default is read-only)
26    #[arg(long, global = true)]
27    pub write: bool,
28
29    #[command(subcommand)]
30    pub command: Commands,
31}
32
33#[derive(Subcommand)]
34pub enum Commands {
35    /// Query using Cypher-like syntax (read-only)
36    Query {
37        /// Cypher-like query (e.g., "MATCH (n:User) RETURN n.name")
38        query: String,
39    },
40
41    /// Show database status
42    Status {
43        /// Use compact output format (single line, no pretty-print)
44        #[arg(long)]
45        compact: bool,
46    },
47
48    /// List all nodes
49    List {
50        /// Filter by kind
51        #[arg(short, long)]
52        kind: Option<String>,
53    },
54
55    /// Breadth-first search
56    Bfs {
57        #[arg(short, long)]
58        start: i64,
59        #[arg(short, long, default_value = "3")]
60        depth: u32,
61    },
62
63    /// Shortest path
64    Path {
65        #[arg(short, long)]
66        from: i64,
67        #[arg(short, long)]
68        to: i64,
69    },
70
71    /// Get neighbors
72    Neighbors {
73        #[arg(short, long)]
74        id: i64,
75        #[arg(short, long, default_value = "outgoing")]
76        direction: Direction,
77    },
78
79    /// Run graph algorithm
80    Algo {
81        #[command(subcommand)]
82        command: AlgoCommands,
83    },
84
85    /// Export graph to file (requires --write)
86    Export {
87        #[arg(short, long)]
88        output: PathBuf,
89    },
90
91    /// Import graph from file (requires --write)
92    Import {
93        #[arg(short, long)]
94        input: PathBuf,
95    },
96
97    /// Insert node (requires --write)
98    Insert {
99        #[arg(short, long)]
100        kind: String,
101        #[arg(short, long)]
102        name: String,
103        #[arg(short, long)]
104        data: Option<String>,
105    },
106
107    /// HNSW vector index operations
108    Hnsw {
109        #[command(subcommand)]
110        command: HnswCommands,
111    },
112}
113
114#[derive(Subcommand)]
115pub enum HnswCommands {
116    /// Create a new HNSW index (requires --write)
117    Create {
118        #[arg(short, long)]
119        name: String,
120        /// Vector dimension
121        #[arg(short, long)]
122        dim: usize,
123        /// Distance metric: cosine, euclidean, or dot
124        #[arg(short, long, default_value = "cosine")]
125        metric: String,
126        /// Max edges per node per layer
127        #[arg(long, default_value = "16")]
128        m: usize,
129        /// Beam width during construction
130        #[arg(long, default_value = "200")]
131        ef_construction: usize,
132    },
133    /// Insert a vector into an existing HNSW index (requires --write)
134    Insert {
135        #[arg(short, long)]
136        name: String,
137        /// Comma-separated f32 values, e.g. `1.0,0.5,-0.25`
138        #[arg(short, long)]
139        vector: String,
140        /// Optional JSON metadata to attach to the vector
141        #[arg(long)]
142        metadata: Option<String>,
143    },
144    /// Search for the k nearest neighbours of a query vector
145    Search {
146        #[arg(short, long)]
147        name: String,
148        #[arg(short, long, default_value = "10")]
149        k: usize,
150        /// Comma-separated f32 values, e.g. `1.0,0.5,-0.25`
151        #[arg(short, long)]
152        vector: String,
153    },
154    /// List all HNSW indices loaded on the graph
155    List,
156    /// Delete an HNSW index (requires --write)
157    Delete {
158        #[arg(short, long)]
159        name: String,
160    },
161}
162
163#[derive(Subcommand)]
164pub enum AlgoCommands {
165    /// PageRank centrality
166    Pagerank {
167        #[arg(short, long, default_value = "100")]
168        iterations: usize,
169    },
170    /// Betweenness centrality
171    Betweenness,
172    /// Weakly-connected components
173    Components,
174    /// Strongly-connected components (Tarjan)
175    Scc,
176    /// Topological sort
177    Topo,
178    /// Louvain community detection
179    Louvain {
180        #[arg(short = 'i', long, default_value = "100")]
181        max_iterations: usize,
182    },
183    /// Label-propagation community detection
184    LabelProp {
185        #[arg(short = 'i', long, default_value = "50")]
186        max_iterations: usize,
187    },
188    /// Find cycles in the graph (bounded)
189    Cycles {
190        #[arg(short, long, default_value = "100")]
191        limit: usize,
192    },
193    /// Dominator tree from a given entry node
194    Dominators {
195        /// Entry node id (root of the dominator tree)
196        #[arg(short, long)]
197        entry: i64,
198    },
199    /// Critical path through the DAG (uniform edge weights = longest path)
200    CriticalPath,
201}
202
203#[derive(Clone, Debug, ValueEnum)]
204pub enum Direction {
205    Incoming,
206    Outgoing,
207    Both,
208}