На этой неделе я начал изучать макросы про c и знаю, как написать fn
с ними. Я пытаюсь создать небольшой типобезопасный построитель запросов для базы данных (Cassandra).
Воспроизведение
Я создал небольшое репо с минимальным кодом, чтобы показать мою проблему: https://github.com/Jasperav/moremacros. Я хочу, чтобы тесты в примере / src / main.rs / test_db_mirror / test_select_queries прошли. Зависимости довольно старые на syn
, quote
и proc-macro2
, потому что я хочу в конечном итоге внести свой вклад в ящик, который, к сожалению, имеет старые зависимости.
Проблема
I иметь структуру, которая 1-на-1 такая же, как таблица базы данных. Это будет выглядеть примерно так:
#[derive(DBMirror)]
struct SomeStruct {
#[partition_key]
id: i32,
#[partition_key]
another_id: i32,
#[clustering_key]
cluster_key: i32,
#[clustering_key]
another_cluster_key: i32,
// Just some column that is not part of the primary key
name: String,
}
Теперь я хочу сгенерировать следующие методы, которые возвращают запрос (&'static str
, все внутри impl
курса):
Все свойства помечены # [partition_key]
(id
и another_id
в данном случае). Все ключи разделения объединяются в один запрос, который выглядит следующим образом:
// 'select_by_' followed by the partition keys
// Parameters are not used here, but they will be used in the 'real' project
pub fn select_by_id_another_id(id: i32, another_id: i32) -> &'static str {
"select * from SomeStruct where id = ? and another_id = ?"
}
Все свойства, помеченные #[clustering_key]
Для каждого свойства, помеченного как #[clustering_key]
, новый метод будет добавлено, что построить запрос всех предыдущих разделов и ключей кластеризации, в том числе его собственный (накопительный). Вот что я имею в виду:
Первое свойство, помеченное как #[clustering_key]
, равно cluster_key
. В запрос ключа раздела должны быть добавлены дополнительные and
и параметр (select_by_id_another_id
). Это должно выглядеть так:
pub fn select_by_id_another_id_cluster_key(id: i32, another_id: i32, cluster_key: i32) -> &'static str {
// Can also call the other macro
"select * from SomeStruct where id = ? and another_id = ? and cluster_key = ?"
}
Есть еще одно свойство, помеченное как #[clustering_key]
. Процесс должен быть повторен: посмотрите на последний письменный запрос и добавьте еще and
:
pub fn select_unique(id: i32, another_id: i32, cluster_key: i32, another_cluster_key: i32) -> &'static str {
// Can also call the other macro
"select * from SomeStruct where id = ? and another_id = ? and cluster_key = ? and another_cluster_key = ?"
}
Этот метод называется select_unique
, так как он содержит все первичные и кластерные ключи, это формирует первичный ключ строка.
Что я пытался
Я пытался использовать повторение, чтобы заставить его работать, но я не понимаю, как я могу добавить кумулятивные параметры и методы. Может быть, выполнение дополнительной работы вне макроса сработает, но я не уверен, как это сделать.