Совокупный процедурный макрос - PullRequest
0 голосов
/ 12 апреля 2020

На этой неделе я начал изучать макросы про 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, так как он содержит все первичные и кластерные ключи, это формирует первичный ключ строка.

Что я пытался

Я пытался использовать повторение, чтобы заставить его работать, но я не понимаю, как я могу добавить кумулятивные параметры и методы. Может быть, выполнение дополнительной работы вне макроса сработает, но я не уверен, как это сделать.

...