Skip to content

Commit 58d4143

Browse files
authored
Merge pull request #1 from frectonz/main
SYNC
2 parents 4a95455 + 3247e84 commit 58d4143

11 files changed

Lines changed: 6071 additions & 5038 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SQLite Studio
2+
3+
SQLite database explorer
4+
5+
## How To Run It
6+
7+
If you are using [Nix](https://nixos.org/).
8+
9+
```bash
10+
nix shell github:frectonz/sqlite-studio
11+
sqlite-studio
12+
```

flake.nix

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
src = pkgs.lib.cleanSourceWith {
3131
src = ./.;
3232
filter = path: type:
33-
(pkgs.lib.hasSuffix "\.sql" path) ||
3433
(pkgs.lib.hasSuffix "\.css" path) ||
3534
(pkgs.lib.hasSuffix "\.js" path) ||
3635
(pkgs.lib.hasSuffix "\.svg" path) ||
@@ -39,9 +38,22 @@
3938
};
4039
commonArgs = { inherit src; };
4140

41+
ui = pkgs.buildNpmPackage {
42+
pname = "ui";
43+
version = "0.0.0";
44+
src = ./ui;
45+
npmDepsHash = "sha256-fIz4WWvzPzQS4CCXvXtf87+ailmDDri1ACnzaB5TP7Y=";
46+
installPhase = ''
47+
cp -pr --reflink=auto -- dist "$out/"
48+
'';
49+
};
50+
4251
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
4352
bin = craneLib.buildPackage (commonArgs // {
4453
inherit cargoArtifacts;
54+
preBuild = ''
55+
cp -pr --reflink=auto -- ${ui} ui/dist
56+
'';
4557
});
4658
in
4759
{
@@ -52,7 +64,6 @@
5264
devShells.default = pkgs.mkShell {
5365
buildInputs = [
5466
pkgs.emmet-ls
55-
pkgs.sqlx-cli
5667
pkgs.cargo-watch
5768
pkgs.rust-analyzer
5869
rustToolchain
@@ -62,7 +73,6 @@
6273
pkgs.nodePackages."@tailwindcss/language-server"
6374

6475
pkgs.nodejs
65-
pkgs.nodePackages.pnpm
6676

6777
pkgs.httpie
6878
];

src/main.rs

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,13 @@ impl TheDB {
193193
table_counts.insert(name, count);
194194
}
195195

196-
let counts = table_counts
196+
let mut counts = table_counts
197197
.into_iter()
198198
.map(|(name, count)| responses::RowCount { name, count })
199199
.collect::<Vec<_>>();
200200

201+
counts.sort_by(|a, b| b.count.cmp(&a.count));
202+
201203
color_eyre::eyre::Ok((tables, indexes, triggers, views, counts))
202204
})
203205
.await??;
@@ -216,9 +218,9 @@ impl TheDB {
216218
})
217219
}
218220

219-
async fn table_names(&self) -> color_eyre::Result<responses::TableNames> {
221+
async fn tables(&self) -> color_eyre::Result<responses::Tables> {
220222
let conn = self.conn.clone();
221-
let names = tokio::task::spawn_blocking(move || {
223+
let tables = tokio::task::spawn_blocking(move || {
222224
let conn = conn.lock().or_else(|e| {
223225
tracing::error!("could not get lock: {e}");
224226
color_eyre::eyre::bail!("could not get lock: {e}")
@@ -227,19 +229,36 @@ impl TheDB {
227229
let mut stmt = conn.prepare(r#"SELECT name FROM sqlite_master WHERE type="table""#)?;
228230
let table_names = stmt
229231
.query_map([], |row| row.get::<_, String>(0))?
230-
.filter_map(|r| r.ok())
231232
.collect::<Vec<_>>();
232233

233-
color_eyre::eyre::Ok(table_names)
234+
let mut table_counts = HashMap::with_capacity(table_names.len());
235+
for name in table_names {
236+
let name = name?;
237+
let count = conn.query_row(&format!("SELECT count(*) FROM {name}"), (), |r| {
238+
r.get::<_, i32>(0)
239+
})?;
240+
241+
table_counts.insert(name, count);
242+
}
243+
244+
let mut counts = table_counts
245+
.into_iter()
246+
.map(|(name, count)| responses::RowCount { name, count })
247+
.collect::<Vec<_>>();
248+
249+
counts.sort_by_key(|r| r.count);
250+
251+
color_eyre::eyre::Ok(counts)
234252
})
235253
.await??;
236254

237-
Ok(responses::TableNames { names })
255+
Ok(responses::Tables { tables })
238256
}
239257

240258
async fn get_table(&self, name: String) -> color_eyre::Result<responses::Table> {
241259
let conn = self.conn.clone();
242-
let (name, sql, columns, rows) = tokio::task::spawn_blocking(move || {
260+
261+
tokio::task::spawn_blocking(move || {
243262
let conn = conn.lock().or_else(|e| {
244263
tracing::error!("could not get lock: {e}");
245264
color_eyre::eyre::bail!("could not get lock: {e}")
@@ -253,15 +272,32 @@ impl TheDB {
253272
|r| r.get::<_, String>(0),
254273
)?;
255274

275+
let row_count = conn.query_row(&format!("SELECT count(*) FROM {name}"), (), |r| {
276+
r.get::<_, i32>(0)
277+
})?;
278+
256279
let mut stmt = conn.prepare(&format!("SELECT * FROM {name}"))?;
257280
let columns = stmt
258281
.column_names()
259282
.into_iter()
260283
.map(ToOwned::to_owned)
261284
.collect::<Vec<_>>();
262285

263-
let columns_len = columns.len();
286+
let table_size = conn.query_row(
287+
"SELECT SUM(pgsize) FROM dbstat WHERE name = ?1",
288+
[&name],
289+
|r| r.get::<_, i32>(0),
290+
)?;
291+
let table_size = helpers::format_size(table_size as u64);
264292

293+
let mut indexes_query =
294+
conn.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name=?1")?;
295+
let indexes = indexes_query
296+
.query_map([&name], |r| r.get::<_, String>(0))?
297+
.filter_map(|r| r.ok())
298+
.collect::<Vec<_>>();
299+
300+
let columns_len = columns.len();
265301
let rows = stmt
266302
.query_map((), |r| {
267303
let mut rows = Vec::with_capacity(columns_len);
@@ -274,16 +310,18 @@ impl TheDB {
274310
.filter_map(|x| x.ok())
275311
.collect::<Vec<_>>();
276312

277-
color_eyre::eyre::Ok((name, sql, columns, rows))
278-
})
279-
.await??;
280-
281-
Ok(responses::Table {
282-
name,
283-
sql,
284-
columns,
285-
rows,
313+
let resp = responses::Table {
314+
name,
315+
sql,
316+
row_count,
317+
table_size,
318+
indexes,
319+
columns,
320+
rows,
321+
};
322+
color_eyre::eyre::Ok(resp)
286323
})
324+
.await?
287325
}
288326
}
289327

@@ -339,14 +377,17 @@ mod responses {
339377
}
340378

341379
#[derive(Serialize)]
342-
pub struct TableNames {
343-
pub names: Vec<String>,
380+
pub struct Tables {
381+
pub tables: Vec<RowCount>,
344382
}
345383

346384
#[derive(Serialize)]
347385
pub struct Table {
348386
pub name: String,
349387
pub sql: String,
388+
pub row_count: i32,
389+
pub table_size: String,
390+
pub indexes: Vec<String>,
350391
pub columns: Vec<String>,
351392
pub rows: Vec<Vec<serde_json::Value>>,
352393
}
@@ -392,8 +433,8 @@ mod handlers {
392433
}
393434

394435
async fn tables(db: TheDB) -> Result<impl warp::Reply, warp::Rejection> {
395-
let tables = db.table_names().await.map_err(|e| {
396-
tracing::error!("error while getting table names: {e}");
436+
let tables = db.tables().await.map_err(|e| {
437+
tracing::error!("error while getting tables: {e}");
397438
warp::reject::custom(rejections::InternalServerError)
398439
})?;
399440
Ok(warp::reply::json(&tables))

0 commit comments

Comments
 (0)