iota_graphql_rpc/server/
compatibility_check.rs1use diesel::{
6 QueryDsl, QueryResult, RunQueryDsl,
7 query_builder::{AstPass, Query, QueryFragment, QueryId},
8 sql_types::Bool,
9};
10
11use crate::{
12 data::{Db, DbConnection, DieselBackend, DieselConn, QueryExecutor},
13 error::Error,
14};
15
16macro_rules! generate_compatibility_check {
26 ($($table:ident),*) => {
27 pub(crate) async fn check_all_tables(db: &Db) -> Result<(), Error> {
28 use futures::future::join_all;
29 use iota_indexer::schema::*;
30
31 let futures = vec![
32 $(
33 db.execute(|conn| Ok::<_, diesel::result::Error>(
34 conn.results::<_, bool>(move || Check {
35 query: $table::table.select($table::all_columns)
36 })
37 .is_ok()
38 ))
39 ),*
40 ];
41
42 let results = join_all(futures).await;
43 if results.into_iter().all(|res| res.unwrap_or(false)) {
44 Ok(())
45 } else {
46 Err(Error::Internal(
47 "One or more tables are missing expected columns".into(),
48 ))
49 }
50 }
51 };
52}
53
54iota_indexer::for_all_tables!(generate_compatibility_check);
55
56#[derive(Debug, Clone, Copy, QueryId)]
57struct Check<Q> {
58 query: Q,
59}
60
61impl<Q: Query> Query for Check<Q> {
62 type SqlType = Bool;
63}
64
65impl<Q> RunQueryDsl<DieselConn> for Check<Q> {}
66
67impl<Q: QueryFragment<DieselBackend>> QueryFragment<DieselBackend> for Check<Q> {
68 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DieselBackend>) -> QueryResult<()> {
69 out.push_sql("SELECT TRUE FROM (");
70 self.query.walk_ast(out.reborrow())?;
71 out.push_sql(") q WHERE FALSE");
72 Ok(())
73 }
74}