1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! `SHOW INDEXES` — the row projection for the index listing.
//!
//! Its own file rather than a section of `schema_ddl.rs` because the listing is
//! a pure projection of
//! [`collect_indexes_structured`](crate::graph::introspection::schema_overview::collect_indexes_structured)
//! and shares nothing with the DDL that installs indexes. `CALL db.indexes()`
//! projects the same collector through `call_clause::indexes_to_rows`, which is
//! why the column list below is the one both agree on.
use super::super::result::{ResultRow, ResultSet};
use crate::datatypes::values::Value;
use crate::graph::dir_graph::DirGraph;
use crate::graph::introspection::schema_overview::{collect_indexes_structured, IndexInfo};
/// Columns `SHOW INDEXES` projects, in order. Identical to `CALL db.indexes()`
/// — one collector, one row shape.
///
/// Neo4j 5's `SHOW INDEXES` also returns `id`, `populationPercent`,
/// `indexProvider`, `owningConstraint`, `lastRead`, and `readCount`. KGLite has
/// no equivalent state for any of them (indexes are built atomically, have no
/// provider, and carry no usage counters), so they are omitted rather than
/// filled with invented values. Documented in CYPHER.md.
pub(crate) const SHOW_INDEXES_COLUMNS: &[&str] = &[
"name",
"type",
"entityType",
"labelsOrTypes",
"properties",
"state",
// KGLite-specific, and null for the index kinds that are maintained on
// every write: a BM25 index catches up at query entry instead, so "is it
// behind, and by how much" is a real question about it.
"stale",
"delta",
// VECTOR rows only: nodes with no vector at all, which no catch-up will
// ever index because catch-up does not embed.
"unembedded",
];
/// `SHOW INDEXES` — a read, over the shared collector named above.
pub(crate) fn show_indexes_result_set(graph: &DirGraph) -> ResultSet {
let mut out = ResultSet::new();
out.rows = collect_indexes_structured(graph)
.iter()
.map(index_info_to_row)
.collect();
out.columns = SHOW_INDEXES_COLUMNS.iter().map(|c| c.to_string()).collect();
out
}
fn index_info_to_row(info: &IndexInfo) -> ResultRow {
let mut row = ResultRow::new();
row.projected
.insert("name".to_string(), Value::String(info.name.clone()));
row.projected.insert(
"type".to_string(),
Value::String(info.kind.neo4j_type().to_string()),
);
row.projected.insert(
"entityType".to_string(),
Value::String(info.entity_type.to_string()),
);
row.projected.insert(
"labelsOrTypes".to_string(),
Value::List(
info.labels_or_types
.iter()
.cloned()
.map(Value::String)
.collect(),
),
);
row.projected.insert(
"properties".to_string(),
Value::List(info.properties.iter().cloned().map(Value::String).collect()),
);
row.projected
.insert("state".to_string(), Value::String(info.state.to_string()));
row.projected.insert(
"stale".to_string(),
info.stale.map_or(Value::Null, Value::Boolean),
);
row.projected.insert(
"delta".to_string(),
info.delta
.map_or(Value::Null, |delta| Value::Int64(delta as i64)),
);
row.projected.insert(
"unembedded".to_string(),
info.unembedded
.map_or(Value::Null, |count| Value::Int64(count as i64)),
);
row
}