-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy pathtables.rs
176 lines (143 loc) · 5.04 KB
/
tables.rs
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use crate::{
builder::CompletionBuilder,
context::CompletionContext,
item::{CompletionItem, CompletionItemKind},
relevance::CompletionRelevanceData,
};
pub fn complete_tables(ctx: &CompletionContext, builder: &mut CompletionBuilder) {
let available_tables = &ctx.schema_cache.tables;
for table in available_tables {
let item = CompletionItem {
label: table.name.clone(),
score: CompletionRelevanceData::Table(table).get_score(ctx),
description: format!("Schema: {}", table.schema),
preselected: false,
kind: CompletionItemKind::Table,
};
builder.add_item(item);
}
}
#[cfg(test)]
mod tests {
use crate::{
CompletionItem, CompletionItemKind, complete,
test_helper::{CURSOR_POS, get_test_deps, get_test_params},
};
#[tokio::test]
async fn autocompletes_simple_table() {
let setup = r#"
create table users (
id serial primary key,
name text,
password text
);
"#;
let query = format!("select * from u{}", CURSOR_POS);
let (tree, cache) = get_test_deps(setup, query.as_str().into()).await;
let params = get_test_params(&tree, &cache, query.as_str().into());
let items = complete(params);
assert!(!items.is_empty());
let best_match = &items[0];
assert_eq!(
best_match.label, "users",
"Does not return the expected table to autocomplete: {}",
best_match.label
)
}
#[tokio::test]
async fn autocompletes_table_alphanumerically() {
let setup = r#"
create table addresses (
id serial primary key
);
create table users (
id serial primary key
);
create table emails (
id serial primary key
);
"#;
let test_cases = vec![
// (format!("select * from us{}", CURSOR_POS), "users"),
// (format!("select * from em{}", CURSOR_POS), "emails"),
(format!("select * from {}", CURSOR_POS), "addresses"),
];
for (query, expected_label) in test_cases {
let (tree, cache) = get_test_deps(setup, query.as_str().into()).await;
let params = get_test_params(&tree, &cache, query.as_str().into());
let items = complete(params);
assert!(!items.is_empty());
let best_match = &items[0];
assert_eq!(
best_match.label, expected_label,
"Does not return the expected table to autocomplete: {}",
best_match.label
)
}
}
#[tokio::test]
async fn autocompletes_table_with_schema() {
let setup = r#"
create schema customer_support;
create schema private;
create table private.user_z (
id serial primary key,
name text,
password text
);
create table customer_support.user_y (
id serial primary key,
request text,
send_at timestamp with time zone
);
"#;
let test_cases = vec![
(format!("select * from u{}", CURSOR_POS), "user_y"), // user_y is preferred alphanumerically
(format!("select * from private.u{}", CURSOR_POS), "user_z"),
(
format!("select * from customer_support.u{}", CURSOR_POS),
"user_y",
),
];
for (query, expected_label) in test_cases {
let (tree, cache) = get_test_deps(setup, query.as_str().into()).await;
let params = get_test_params(&tree, &cache, query.as_str().into());
let items = complete(params);
assert!(!items.is_empty());
let best_match = &items[0];
assert_eq!(
best_match.label, expected_label,
"Does not return the expected table to autocomplete: {}",
best_match.label
)
}
}
#[tokio::test]
async fn prefers_table_in_from_clause() {
let setup = r#"
create table coos (
id serial primary key,
name text
);
create or replace function cool()
returns trigger
language plpgsql
security invoker
as $$
begin
raise exception 'dont matter';
end;
$$;
"#;
let query = format!(r#"select * from coo{}"#, CURSOR_POS);
let (tree, cache) = get_test_deps(setup, query.as_str().into()).await;
let params = get_test_params(&tree, &cache, query.as_str().into());
let items = complete(params);
let CompletionItem { label, kind, .. } = items
.into_iter()
.next()
.expect("Should return at least one completion item");
assert_eq!(label, "coos");
assert_eq!(kind, CompletionItemKind::Table);
}
}