Могу ли я, используя крейт rusqlite, передать массив в качестве параметра для предложения, содержащего «IN»?

Я использую ящик rusqlite в Rust для выполнения SQL-запросов к базе данных SQLite. У меня есть запрос, который должен фильтровать строки на основе списка значений с использованием предложения IN. Я хотел бы знать, есть ли способ передать массив или вектор в качестве параметра для предложения IN напрямую, вместо создания заполнителей для каждого элемента в списке.

Например, допустим, у меня есть следующий запрос:

SELECT * FROM articles WHERE url IN (?);

Я хотел бы передать вектор Rust в качестве параметра для ? заполнитель, например:

let urls: Vec<String> = vec![
    "example1.com".to_string(),
    "example2.com".to_string(),
];

let result: Vec<String> = easy_query!(query, params![urls], Vec<String>)?;

Есть ли более простой способ добиться этого без необходимости создавать заполнители для каждого элемента в массиве или векторе и передавать их как отдельные параметры?

Заранее спасибо за вашу помощь.

Примечание: easy_query! макрос, показанный в примере, не является частью крейта rusqlite. Это специальный синтаксический сахар, который я использую для упрощения процесса запроса с меньшим количеством детализации. Вопрос по-прежнему сосредоточен на передаче массива или вектора в качестве параметра для предложения IN непосредственно в rusqlite.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
0
0
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Кажется, нет никакого способа напрямую передать массив в IN SQLite, вам нужны заполнители, но вы можете сделать это относительно просто, используя std::iter::repeat() и collect::<Vec<_>>().join(",") что-то вроде:

use rusqlite::{params, Connection};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let conn = Connection::open_in_memory()?;

    let names = vec!["Alice", "Bob", "Charlie"];
    let placeholders: String = std::iter::repeat("?").take(names.len()).collect::<Vec<_>>().join(",");

    let ids: Vec<i64> = conn
        .prepare(&format!("SELECT id FROM users WHERE name IN ({})", placeholders))
        .unwrap()
        .query_map(names, |row| row.get(0))?
        .map(|id| id.unwrap())
        .collect();

    println!("IDs: {:?}", ids);

    Ok(())
}

детская площадка (показывает только сгенерированные заполнители)

NB: Postgres поддерживает использование массивов, но для этого используется ANY вместо IN, например.

SELECT * FROM my_table WHERE my_column = ANY(ARRAY[1, 2, 3])

но SQLite (насколько я знаю об этом продукте) не предлагает этого.

ps: не удалось увидеть изображение pastbin из текущего соединения, поэтому не могу комментировать макрос

Paul Maxwell 03.05.2023 14:58
Ответ принят как подходящий

Для SQLite есть расширение carray. А для rusqlite есть расширение rarray.

В чем разница между carray и rarray? Должен ли я использовать версию пакета Rustqlite, чтобы это работало?

Felipe 08.05.2023 18:14

Связанный: stackoverflow.com/a/69231487/450148

Felipe 08.05.2023 18:15

Carray поддерживает массив C. rarray поддерживает вектор ржавчины. Требуется только последняя версия SQLite (>= 3.20.0).

gwen 03.06.2023 06:33

Другие вопросы по теме