Skip to content

Commit 1e19c9b

Browse files
committed
faster autocomplete
1 parent 9712ab8 commit 1e19c9b

1 file changed

Lines changed: 197 additions & 25 deletions

File tree

src/db/postgres.rs

Lines changed: 197 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::dsl::{
1313
use async_trait::async_trait;
1414
use chrono::{DateTime, Utc};
1515
use sqlx::{Execute, PgPool, Postgres, QueryBuilder, Transaction, types::Json};
16+
use sqlx::postgres::PgArguments;
1617
use std::{
1718
collections::{BTreeMap, HashMap, HashSet},
1819
io::Read,
@@ -1942,18 +1943,46 @@ ORDER BY idx
19421943
) -> Result<Vec<String>, DbError> {
19431944
let escaped = escape_sql_like_literal(term);
19441945
let pattern = format!("%{}%", escaped);
1945-
let rows: Vec<String> = sqlx::query_scalar(
1946+
let mut query = sqlx::query_scalar(
19461947
"SELECT DISTINCT repository \
19471948
FROM files \
19481949
WHERE repository ILIKE $1 ESCAPE '\\' \
19491950
ORDER BY repository \
19501951
LIMIT $2",
19511952
)
19521953
.bind(pattern)
1953-
.bind(limit)
1954-
.fetch_all(&self.pool)
1955-
.await
1956-
.map_err(|e| DbError::Database(e.to_string()))?;
1954+
.bind(limit);
1955+
1956+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
1957+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
1958+
if let Ok(Some(args)) = query.take_arguments() {
1959+
let args: PgArguments = args;
1960+
let explain_args = args.clone();
1961+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
1962+
.fetch_all(&self.pool)
1963+
.await
1964+
{
1965+
Ok(rows) => {
1966+
for line in rows {
1967+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
1968+
}
1969+
}
1970+
Err(err) => {
1971+
tracing::warn!(
1972+
target: "pointer::autocomplete_sql",
1973+
"failed to run EXPLAIN: {}",
1974+
err
1975+
);
1976+
}
1977+
}
1978+
query = sqlx::query_scalar_with::<Postgres, String, PgArguments>(query.sql(), args);
1979+
}
1980+
}
1981+
1982+
let rows: Vec<String> = query
1983+
.fetch_all(&self.pool)
1984+
.await
1985+
.map_err(|e| DbError::Database(e.to_string()))?;
19571986

19581987
Ok(rows)
19591988
}
@@ -1994,8 +2023,34 @@ ORDER BY idx
19942023
qb.push(" ESCAPE '\\' ORDER BY dir LIMIT ");
19952024
qb.push_bind(limit);
19962025

1997-
let rows: Vec<String> = qb
1998-
.build_query_scalar()
2026+
let mut query = qb.build_query_scalar::<String>();
2027+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
2028+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
2029+
if let Ok(Some(args)) = query.take_arguments() {
2030+
let args: PgArguments = args;
2031+
let explain_args = args.clone();
2032+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
2033+
.fetch_all(&self.pool)
2034+
.await
2035+
{
2036+
Ok(rows) => {
2037+
for line in rows {
2038+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
2039+
}
2040+
}
2041+
Err(err) => {
2042+
tracing::warn!(
2043+
target: "pointer::autocomplete_sql",
2044+
"failed to run EXPLAIN: {}",
2045+
err
2046+
);
2047+
}
2048+
}
2049+
query = sqlx::query_scalar_with::<Postgres, String, PgArguments>(query.sql(), args);
2050+
}
2051+
}
2052+
2053+
let rows: Vec<String> = query
19992054
.fetch_all(&self.pool)
20002055
.await
20012056
.map_err(|e| DbError::Database(e.to_string()))?;
@@ -2027,8 +2082,34 @@ ORDER BY idx
20272082
qb.push(" ESCAPE '\\' ORDER BY file_path LIMIT ");
20282083
qb.push_bind(limit);
20292084

2030-
let rows: Vec<String> = qb
2031-
.build_query_scalar()
2085+
let mut query = qb.build_query_scalar::<String>();
2086+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
2087+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
2088+
if let Ok(Some(args)) = query.take_arguments() {
2089+
let args: PgArguments = args;
2090+
let explain_args = args.clone();
2091+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
2092+
.fetch_all(&self.pool)
2093+
.await
2094+
{
2095+
Ok(rows) => {
2096+
for line in rows {
2097+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
2098+
}
2099+
}
2100+
Err(err) => {
2101+
tracing::warn!(
2102+
target: "pointer::autocomplete_sql",
2103+
"failed to run EXPLAIN: {}",
2104+
err
2105+
);
2106+
}
2107+
}
2108+
query = sqlx::query_scalar_with::<Postgres, String, PgArguments>(query.sql(), args);
2109+
}
2110+
}
2111+
2112+
let rows: Vec<String> = query
20322113
.fetch_all(&self.pool)
20332114
.await
20342115
.map_err(|e| DbError::Database(e.to_string()))?;
@@ -2061,8 +2142,37 @@ ORDER BY idx
20612142
qb.push(" ESCAPE '\\' ORDER BY cb.language LIMIT ");
20622143
qb.push_bind(limit);
20632144

2064-
let rows: Vec<Option<String>> = qb
2065-
.build_query_scalar()
2145+
let mut query = qb.build_query_scalar::<Option<String>>();
2146+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
2147+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
2148+
if let Ok(Some(args)) = query.take_arguments() {
2149+
let args: PgArguments = args;
2150+
let explain_args = args.clone();
2151+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
2152+
.fetch_all(&self.pool)
2153+
.await
2154+
{
2155+
Ok(rows) => {
2156+
for line in rows {
2157+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
2158+
}
2159+
}
2160+
Err(err) => {
2161+
tracing::warn!(
2162+
target: "pointer::autocomplete_sql",
2163+
"failed to run EXPLAIN: {}",
2164+
err
2165+
);
2166+
}
2167+
}
2168+
query = sqlx::query_scalar_with::<Postgres, Option<String>, PgArguments>(
2169+
query.sql(),
2170+
args,
2171+
);
2172+
}
2173+
}
2174+
2175+
let rows: Vec<Option<String>> = query
20662176
.fetch_all(&self.pool)
20672177
.await
20682178
.map_err(|e| DbError::Database(e.to_string()))?;
@@ -2094,8 +2204,34 @@ ORDER BY idx
20942204
qb.push(" ESCAPE '\\' ORDER BY branch LIMIT ");
20952205
qb.push_bind(limit);
20962206

2097-
let rows: Vec<String> = qb
2098-
.build_query_scalar()
2207+
let mut query = qb.build_query_scalar::<String>();
2208+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
2209+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
2210+
if let Ok(Some(args)) = query.take_arguments() {
2211+
let args: PgArguments = args;
2212+
let explain_args = args.clone();
2213+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
2214+
.fetch_all(&self.pool)
2215+
.await
2216+
{
2217+
Ok(rows) => {
2218+
for line in rows {
2219+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
2220+
}
2221+
}
2222+
Err(err) => {
2223+
tracing::warn!(
2224+
target: "pointer::autocomplete_sql",
2225+
"failed to run EXPLAIN: {}",
2226+
err
2227+
);
2228+
}
2229+
}
2230+
query = sqlx::query_scalar_with::<Postgres, String, PgArguments>(query.sql(), args);
2231+
}
2232+
}
2233+
2234+
let rows: Vec<String> = query
20992235
.fetch_all(&self.pool)
21002236
.await
21012237
.map_err(|e| DbError::Database(e.to_string()))?;
@@ -2110,23 +2246,59 @@ ORDER BY idx
21102246
) -> Result<Vec<SymbolSuggestion>, DbError> {
21112247
let escaped = escape_sql_like_literal(term);
21122248
let pattern = format!("%{}%", escaped);
2113-
let rows: Vec<(String, String, String)> = sqlx::query_as(
2114-
"SELECT
2115-
s.name_lc,
2249+
let mut query = sqlx::query_as(
2250+
"WITH matches AS (
2251+
SELECT us.name_lc
2252+
FROM unique_symbols us
2253+
WHERE us.name_lc ILIKE $1 ESCAPE '\\'
2254+
LIMIT $2
2255+
)
2256+
SELECT
2257+
m.name_lc,
21162258
MIN(f.repository) AS repository,
21172259
MIN(f.file_path) AS file_path
2118-
FROM symbols s
2260+
FROM matches m
2261+
JOIN symbols s ON s.name_lc = m.name_lc
21192262
JOIN files f ON f.content_hash = s.content_hash
2120-
WHERE s.name_lc ILIKE $1 ESCAPE '\\'
2121-
GROUP BY s.name_lc
2122-
ORDER BY s.name_lc
2123-
LIMIT $2",
2263+
GROUP BY m.name_lc
2264+
ORDER BY m.name_lc",
21242265
)
21252266
.bind(pattern)
2126-
.bind(limit)
2127-
.fetch_all(&self.pool)
2128-
.await
2129-
.map_err(|e| DbError::Database(e.to_string()))?;
2267+
.bind(limit);
2268+
2269+
if std::env::var("POINTER_EXPLAIN_SEARCH_SQL").is_ok() {
2270+
let sql = format!("EXPLAIN (ANALYZE, VERBOSE, BUFFERS) {}", query.sql());
2271+
if let Ok(Some(args)) = query.take_arguments() {
2272+
let args: PgArguments = args;
2273+
let explain_args = args.clone();
2274+
match sqlx::query_scalar_with::<Postgres, String, PgArguments>(&sql, explain_args)
2275+
.fetch_all(&self.pool)
2276+
.await
2277+
{
2278+
Ok(rows) => {
2279+
for line in rows {
2280+
tracing::info!(target: "pointer::autocomplete_sql", "{}", line);
2281+
}
2282+
}
2283+
Err(err) => {
2284+
tracing::warn!(
2285+
target: "pointer::autocomplete_sql",
2286+
"failed to run EXPLAIN: {}",
2287+
err
2288+
);
2289+
}
2290+
}
2291+
query = sqlx::query_as_with::<Postgres, (String, String, String), PgArguments>(
2292+
query.sql(),
2293+
args,
2294+
);
2295+
}
2296+
}
2297+
2298+
let rows: Vec<(String, String, String)> = query
2299+
.fetch_all(&self.pool)
2300+
.await
2301+
.map_err(|e| DbError::Database(e.to_string()))?;
21302302

21312303
Ok(rows
21322304
.into_iter()

0 commit comments

Comments
 (0)