sqlite where IN for id entry (#1988)

Fixes #258
This commit is contained in:
James Hodgkinson 2023-08-17 13:32:41 +10:00 committed by GitHub
parent 003234c2d0
commit 46f9a36a1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 41 deletions

View file

@ -24,7 +24,7 @@ members = [
"libs/file_permissions",
"libs/profiles",
"libs/sketching",
"libs/users"
"libs/users",
]
[workspace.package]
@ -32,7 +32,7 @@ version = "1.1.0-rc.14-dev"
authors = [
"William Brown <william@blackhats.net.au>",
"James Hodgkinson <james@terminaloutcomes.com>",
]
]
rust-version = "1.66"
edition = "2021"
license = "MPL-2.0"
@ -55,7 +55,17 @@ serde_with = "3.2.0"
argon2 = { version = "0.5.1", features = ["alloc"] }
async-recursion = "1.0.4"
async-trait = "^0.1.73"
axum = {version = "0.6.20", features = ["json", "http2", "macros", "tracing", "headers", "original-uri", "query", "form", "http2"]}
axum = { version = "0.6.20", features = [
"json",
"http2",
"macros",
"tracing",
"headers",
"original-uri",
"query",
"form",
"http2",
] }
axum-csp = { version = "0.0.5" }
base32 = "^0.4.0"
base64 = "^0.21.0"
@ -117,7 +127,13 @@ qrcode = "^0.12.0"
quote = "1"
rand = "^0.8.5"
regex = "1.9.3"
reqwest = { version = "0.11.18", default-features = false, features=["cookies", "json", "gzip", "native-tls", "native-tls-alpn"] }
reqwest = { version = "0.11.18", default-features = false, features = [
"cookies",
"json",
"gzip",
"native-tls",
"native-tls-alpn",
] }
rpassword = "^7.2.0"
rusqlite = "^0.28.0"

View file

@ -79,11 +79,11 @@ serde_with = { workspace = true }
# because windows really can't build without the bundled one
[target.'cfg(target_family = "windows")'.dependencies]
rusqlite = { workspace = true, features = ["bundled"] }
rusqlite = { workspace = true, features = ["array", "bundled"] }
whoami = { workspace = true }
[target.'cfg(not(target_family = "windows"))'.dependencies]
rusqlite = { workspace = true }
rusqlite = { workspace = true, features = ["array"] }
kanidm_utils_users = { workspace = true }
[features]

View file

@ -8,6 +8,7 @@ use std::time::Duration;
use hashbrown::HashMap;
use idlset::v2::IDLBitRange;
use kanidm_proto::v1::{ConsistencyError, OperationError};
use rusqlite::vtab::array::Array;
use rusqlite::{Connection, OpenFlags, OptionalExtension};
use uuid::Uuid;
@ -157,47 +158,31 @@ pub trait IdlSqliteTransaction {
.collect()
}
IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => {
let mut id_list: Vec<rusqlite::types::Value> = vec![];
for item in idli.into_iter() {
id_list.push(rusqlite::types::Value::Integer(
i64::try_from(item).map_err(|_| OperationError::InvalidEntryId)?,
));
}
let mut stmt = self
.get_conn()?
.prepare(&format!(
"SELECT id, data FROM {}.id2entry WHERE id = :idl",
"SELECT id, data FROM {}.id2entry WHERE id IN (:idl)",
self.get_db_name()
))
.map_err(sqlite_error)?;
// TODO #258: Can this actually just load in a single select?
// TODO #258: I have no idea how to make this an iterator chain ... so what
// I have now is probably really bad :(
let mut results = Vec::new();
/*
let decompressed: Result<Vec<i64>, _> = idli.into_iter()
.map(|u| i64::try_from(u).map_err(|_| OperationError::InvalidEntryId))
.collect();
*/
for id in idli {
let iid = i64::try_from(id).map_err(|_| OperationError::InvalidEntryId)?;
let id2entry_iter = stmt
.query_map([&iid], |row| {
Ok(IdSqliteEntry {
id: row.get(0)?,
data: row.get(1)?,
})
})
.map_err(sqlite_error)?;
let r: Result<Vec<_>, _> = id2entry_iter
.map(|v| {
v.map_err(sqlite_error).and_then(|ise| {
// Convert the idsqlite to id raw
ise.try_into()
})
})
.collect();
let mut r = r?;
results.append(&mut r);
}
let mut results: Vec<IdRawEntry> = vec![];
let _ = stmt
.query_map(&[(":idl", &Array::from(id_list))], |row| {
results.push(IdRawEntry {
id: row.get(0)?,
data: row.get(1)?,
});
Ok(())
})
.map_err(sqlite_error)?;
Ok(results)
}
}

View file

@ -65,7 +65,15 @@ serde_json = { workspace = true }
sketching = { workspace = true }
toml = { workspace = true }
tokio = { workspace = true, features = ["rt", "fs", "macros", "sync", "time", "net", "io-util"] }
tokio = { workspace = true, features = [
"rt",
"fs",
"macros",
"sync",
"time",
"net",
"io-util",
] }
tokio-util = { workspace = true, features = ["codec"] }
tracing = { workspace = true }
tss-esapi = { workspace = true, optional = true }