sqlx_adapter/
actions.rs

1#![allow(clippy::suspicious_else_formatting)]
2#![allow(clippy::toplevel_ref_arg)]
3use crate::Error;
4use casbin::{error::AdapterError, Error as CasbinError, Filter, Result};
5use sqlx::error::Error as SqlxError;
6
7use crate::models::{CasbinRule, NewCasbinRule};
8
9#[cfg(feature = "postgres")]
10use sqlx::postgres::PgQueryResult;
11
12#[cfg(feature = "mysql")]
13use sqlx::mysql::MySqlQueryResult;
14
15#[cfg(feature = "sqlite")]
16use sqlx::sqlite::SqliteQueryResult;
17
18#[cfg(feature = "postgres")]
19pub type ConnectionPool = sqlx::PgPool;
20
21#[cfg(feature = "mysql")]
22pub type ConnectionPool = sqlx::MySqlPool;
23
24#[cfg(feature = "sqlite")]
25pub type ConnectionPool = sqlx::SqlitePool;
26
27#[cfg(feature = "postgres")]
28pub async fn new(conn: &ConnectionPool) -> Result<PgQueryResult> {
29    sqlx::query!(
30        "CREATE TABLE IF NOT EXISTS casbin_rule (
31                    id SERIAL PRIMARY KEY,
32                    ptype VARCHAR NOT NULL,
33                    v0 VARCHAR NOT NULL,
34                    v1 VARCHAR NOT NULL,
35                    v2 VARCHAR NOT NULL,
36                    v3 VARCHAR NOT NULL,
37                    v4 VARCHAR NOT NULL,
38                    v5 VARCHAR NOT NULL,
39                    CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
40                    );
41        "
42    )
43    .execute(conn)
44    .await
45    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
46}
47
48#[cfg(feature = "sqlite")]
49pub async fn new(conn: &ConnectionPool) -> Result<SqliteQueryResult> {
50    sqlx::query!(
51        "CREATE TABLE IF NOT EXISTS casbin_rule (
52                    id SERIAL PRIMARY KEY,
53                    ptype VARCHAR NOT NULL,
54                    v0 VARCHAR NOT NULL,
55                    v1 VARCHAR NOT NULL,
56                    v2 VARCHAR NOT NULL,
57                    v3 VARCHAR NOT NULL,
58                    v4 VARCHAR NOT NULL,
59                    v5 VARCHAR NOT NULL,
60                    CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
61                    );
62        "
63    )
64    .execute(conn)
65    .await
66    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
67}
68
69#[cfg(feature = "mysql")]
70pub async fn new(conn: &ConnectionPool) -> Result<MySqlQueryResult> {
71    sqlx::query!(
72        "CREATE TABLE IF NOT EXISTS casbin_rule (
73                    id INT NOT NULL AUTO_INCREMENT,
74                    ptype VARCHAR(12) NOT NULL,
75                    v0 VARCHAR(128) NOT NULL,
76                    v1 VARCHAR(128) NOT NULL,
77                    v2 VARCHAR(128) NOT NULL,
78                    v3 VARCHAR(128) NOT NULL,
79                    v4 VARCHAR(128) NOT NULL,
80                    v5 VARCHAR(128) NOT NULL,
81                    PRIMARY KEY(id),
82                    CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
83                ) ENGINE=InnoDB DEFAULT CHARSET=utf8;",
84    )
85    .execute(conn)
86    .await
87    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
88}
89
90#[cfg(feature = "postgres")]
91pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
92    let rule = normalize_casbin_rule(rule);
93    sqlx::query!(
94        "DELETE FROM casbin_rule WHERE
95                    ptype = $1 AND
96                    v0 = $2 AND
97                    v1 = $3 AND
98                    v2 = $4 AND
99                    v3 = $5 AND
100                    v4 = $6 AND
101                    v5 = $7",
102        pt,
103        rule[0],
104        rule[1],
105        rule[2],
106        rule[3],
107        rule[4],
108        rule[5]
109    )
110    .execute(conn)
111    .await
112    .map(|n| PgQueryResult::rows_affected(&n) == 1)
113    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
114}
115
116#[cfg(feature = "sqlite")]
117pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
118    let rule = normalize_casbin_rule(rule);
119    sqlx::query!(
120        "DELETE FROM casbin_rule WHERE
121                    ptype = ?1 AND
122                    v0 = ?2 AND
123                    v1 = ?3 AND
124                    v2 = ?4 AND
125                    v3 = ?5 AND
126                    v4 = ?6 AND
127                    v5 = ?7",
128        pt,
129        rule[0],
130        rule[1],
131        rule[2],
132        rule[3],
133        rule[4],
134        rule[5]
135    )
136    .execute(conn)
137    .await
138    .map(|n| SqliteQueryResult::rows_affected(&n) == 1)
139    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
140}
141
142#[cfg(feature = "mysql")]
143pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
144    let rule = normalize_casbin_rule(rule);
145    sqlx::query!(
146        "DELETE FROM casbin_rule WHERE
147                    ptype = ? AND
148                    v0 = ? AND
149                    v1 = ? AND
150                    v2 = ? AND
151                    v3 = ? AND
152                    v4 = ? AND
153                    v5 = ?",
154        pt,
155        rule[0],
156        rule[1],
157        rule[2],
158        rule[3],
159        rule[4],
160        rule[5]
161    )
162    .execute(conn)
163    .await
164    .map(|n| MySqlQueryResult::rows_affected(&n) == 1)
165    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
166}
167
168#[cfg(feature = "postgres")]
169pub async fn remove_policies(
170    conn: &ConnectionPool,
171    pt: &str,
172    rules: Vec<Vec<String>>,
173) -> Result<bool> {
174    let mut transaction = conn
175        .begin()
176        .await
177        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
178    for rule in rules {
179        let rule = normalize_casbin_rule(rule);
180        sqlx::query!(
181            "DELETE FROM casbin_rule WHERE
182                    ptype = $1 AND
183                    v0 = $2 AND
184                    v1 = $3 AND
185                    v2 = $4 AND
186                    v3 = $5 AND
187                    v4 = $6 AND
188                    v5 = $7",
189            pt,
190            rule[0],
191            rule[1],
192            rule[2],
193            rule[3],
194            rule[4],
195            rule[5]
196        )
197        .execute(&mut *transaction)
198        .await
199        .and_then(|n| {
200            if PgQueryResult::rows_affected(&n) == 1 {
201                Ok(true)
202            } else {
203                Err(SqlxError::RowNotFound)
204            }
205        })
206        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
207    }
208    transaction
209        .commit()
210        .await
211        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
212    Ok(true)
213}
214
215#[cfg(feature = "sqlite")]
216pub async fn remove_policies(
217    conn: &ConnectionPool,
218    pt: &str,
219    rules: Vec<Vec<String>>,
220) -> Result<bool> {
221    let mut transaction = conn
222        .begin()
223        .await
224        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
225    for rule in rules {
226        let rule = normalize_casbin_rule(rule);
227        sqlx::query!(
228            "DELETE FROM casbin_rule WHERE
229                    ptype = ?1 AND
230                    v0 = ?2 AND
231                    v1 = ?3 AND
232                    v2 = ?4 AND
233                    v3 = ?5 AND
234                    v4 = ?6 AND
235                    v5 = ?7",
236            pt,
237            rule[0],
238            rule[1],
239            rule[2],
240            rule[3],
241            rule[4],
242            rule[5]
243        )
244        .execute(&mut *transaction)
245        .await
246        .and_then(|n| {
247            if SqliteQueryResult::rows_affected(&n) == 1 {
248                Ok(true)
249            } else {
250                Err(SqlxError::RowNotFound)
251            }
252        })
253        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
254    }
255    transaction
256        .commit()
257        .await
258        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
259    Ok(true)
260}
261
262#[cfg(feature = "mysql")]
263pub async fn remove_policies(
264    conn: &ConnectionPool,
265    pt: &str,
266    rules: Vec<Vec<String>>,
267) -> Result<bool> {
268    let mut transaction = conn
269        .begin()
270        .await
271        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
272    for rule in rules {
273        let rule = normalize_casbin_rule(rule);
274        sqlx::query!(
275            "DELETE FROM casbin_rule WHERE
276                    ptype = ? AND
277                    v0 = ? AND
278                    v1 = ? AND
279                    v2 = ? AND
280                    v3 = ? AND
281                    v4 = ? AND
282                    v5 = ?",
283            pt,
284            rule[0],
285            rule[1],
286            rule[2],
287            rule[3],
288            rule[4],
289            rule[5]
290        )
291        .execute(&mut *transaction)
292        .await
293        .and_then(|n| {
294            if MySqlQueryResult::rows_affected(&n) == 1 {
295                Ok(true)
296            } else {
297                Err(SqlxError::RowNotFound)
298            }
299        })
300        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
301    }
302    transaction
303        .commit()
304        .await
305        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
306    Ok(true)
307}
308
309#[cfg(feature = "postgres")]
310pub async fn remove_filtered_policy(
311    conn: &ConnectionPool,
312    pt: &str,
313    field_index: usize,
314    field_values: Vec<String>,
315) -> Result<bool> {
316    let field_values = normalize_casbin_rule_option(field_values);
317    let boxed_query = if field_index == 5 {
318        Box::new(sqlx::query!(
319            "DELETE FROM casbin_rule WHERE
320                    ptype = $1 AND
321                    (v5 is NULL OR v5 = COALESCE($2,v5))",
322            pt.to_string(),
323            field_values[0]
324        ))
325    } else if field_index == 4 {
326        Box::new(sqlx::query!(
327            "DELETE FROM casbin_rule WHERE
328                    ptype = $1 AND
329                    (v4 is NULL OR v4 = COALESCE($2,v4)) AND
330                    (v5 is NULL OR v5 = COALESCE($3,v5))",
331            pt,
332            field_values[0],
333            field_values[1]
334        ))
335    } else if field_index == 3 {
336        Box::new(sqlx::query!(
337            "DELETE FROM casbin_rule WHERE
338                    ptype = $1 AND
339                    (v3 is NULL OR v3 = COALESCE($2,v3)) AND
340                    (v4 is NULL OR v4 = COALESCE($3,v4)) AND
341                    (v5 is NULL OR v5 = COALESCE($4,v5))",
342            pt,
343            field_values[0],
344            field_values[1],
345            field_values[2]
346        ))
347    } else if field_index == 2 {
348        Box::new(sqlx::query!(
349            "DELETE FROM casbin_rule WHERE
350                    ptype = $1 AND
351                    (v2 is NULL OR v2 = COALESCE($2,v2)) AND
352                    (v3 is NULL OR v3 = COALESCE($3,v3)) AND
353                    (v4 is NULL OR v4 = COALESCE($4,v4)) AND
354                    (v5 is NULL OR v5 = COALESCE($5,v5))",
355            pt,
356            field_values[0],
357            field_values[1],
358            field_values[2],
359            field_values[3]
360        ))
361    } else if field_index == 1 {
362        Box::new(sqlx::query!(
363            "DELETE FROM casbin_rule WHERE
364                    ptype = $1 AND
365                    (v1 is NULL OR v1 = COALESCE($2,v1)) AND
366                    (v2 is NULL OR v2 = COALESCE($3,v2)) AND
367                    (v3 is NULL OR v3 = COALESCE($4,v3)) AND
368                    (v4 is NULL OR v4 = COALESCE($5,v4)) AND
369                    (v5 is NULL OR v5 = COALESCE($6,v5))",
370            pt,
371            field_values[0],
372            field_values[1],
373            field_values[2],
374            field_values[3],
375            field_values[4]
376        ))
377    } else {
378        Box::new(sqlx::query!(
379            "DELETE FROM casbin_rule WHERE
380                    ptype = $1 AND
381                    (v0 is NULL OR v0 = COALESCE($2,v0)) AND
382                    (v1 is NULL OR v1 = COALESCE($3,v1)) AND
383                    (v2 is NULL OR v2 = COALESCE($4,v2)) AND
384                    (v3 is NULL OR v3 = COALESCE($5,v3)) AND
385                    (v4 is NULL OR v4 = COALESCE($6,v4)) AND
386                    (v5 is NULL OR v5 = COALESCE($7,v5))",
387            pt,
388            field_values[0],
389            field_values[1],
390            field_values[2],
391            field_values[3],
392            field_values[4],
393            field_values[5]
394        ))
395    };
396
397    boxed_query
398        .execute(conn)
399        .await
400        .map(|n| PgQueryResult::rows_affected(&n) >= 1)
401        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
402}
403
404#[cfg(feature = "sqlite")]
405pub async fn remove_filtered_policy(
406    conn: &ConnectionPool,
407    pt: &str,
408    field_index: usize,
409    field_values: Vec<String>,
410) -> Result<bool> {
411    let field_values = normalize_casbin_rule_option(field_values);
412    let boxed_query = if field_index == 5 {
413        Box::new(sqlx::query!(
414            "DELETE FROM casbin_rule WHERE
415                    ptype = $1 AND
416                    (v5 is NULL OR v5 = COALESCE(?2,v5))",
417            pt,
418            field_values[0]
419        ))
420    } else if field_index == 4 {
421        Box::new(sqlx::query!(
422            "DELETE FROM casbin_rule WHERE
423                    ptype = ?1 AND
424                    (v4 is NULL OR v4 = COALESCE(?2,v4)) AND
425                    (v5 is NULL OR v5 = COALESCE(?3,v5))",
426            pt,
427            field_values[0],
428            field_values[1]
429        ))
430    } else if field_index == 3 {
431        Box::new(sqlx::query!(
432            "DELETE FROM casbin_rule WHERE
433                    ptype = ?1 AND
434                    (v3 is NULL OR v3 = COALESCE(?2,v3)) AND
435                    (v4 is NULL OR v4 = COALESCE(?3,v4)) AND
436                    (v5 is NULL OR v5 = COALESCE(?4,v5))",
437            pt,
438            field_values[0],
439            field_values[1],
440            field_values[2]
441        ))
442    } else if field_index == 2 {
443        Box::new(sqlx::query!(
444            "DELETE FROM casbin_rule WHERE
445                    ptype = ?1 AND
446                    (v2 is NULL OR v2 = COALESCE(?2,v2)) AND
447                    (v3 is NULL OR v3 = COALESCE(?3,v3)) AND
448                    (v4 is NULL OR v4 = COALESCE(?4,v4)) AND
449                    (v5 is NULL OR v5 = COALESCE(?5,v5))",
450            pt,
451            field_values[0],
452            field_values[1],
453            field_values[2],
454            field_values[3]
455        ))
456    } else if field_index == 1 {
457        Box::new(sqlx::query!(
458            "DELETE FROM casbin_rule WHERE
459                    ptype = ?1 AND
460                    (v1 is NULL OR v1 = COALESCE(?2,v1)) AND
461                    (v2 is NULL OR v2 = COALESCE(?3,v2)) AND
462                    (v3 is NULL OR v3 = COALESCE(?4,v3)) AND
463                    (v4 is NULL OR v4 = COALESCE(?5,v4)) AND
464                    (v5 is NULL OR v5 = COALESCE(?6,v5))",
465            pt,
466            field_values[0],
467            field_values[1],
468            field_values[2],
469            field_values[3],
470            field_values[4]
471        ))
472    } else {
473        Box::new(sqlx::query!(
474            "DELETE FROM casbin_rule WHERE
475                    ptype = ?1 AND
476                    (v0 is NULL OR v0 = COALESCE(?2,v0)) AND
477                    (v1 is NULL OR v1 = COALESCE(?3,v1)) AND
478                    (v2 is NULL OR v2 = COALESCE(?4,v2)) AND
479                    (v3 is NULL OR v3 = COALESCE(?5,v3)) AND
480                    (v4 is NULL OR v4 = COALESCE(?6,v4)) AND
481                    (v5 is NULL OR v5 = COALESCE(?7,v5))",
482            pt,
483            field_values[0],
484            field_values[1],
485            field_values[2],
486            field_values[3],
487            field_values[4],
488            field_values[5]
489        ))
490    };
491
492    boxed_query
493        .execute(conn)
494        .await
495        .map(|n| SqliteQueryResult::rows_affected(&n) >= 1)
496        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
497}
498
499#[cfg(feature = "mysql")]
500pub async fn remove_filtered_policy(
501    conn: &ConnectionPool,
502    pt: &str,
503    field_index: usize,
504    field_values: Vec<String>,
505) -> Result<bool> {
506    let field_values = normalize_casbin_rule_option(field_values);
507    let boxed_query = if field_index == 5 {
508        Box::new(sqlx::query!(
509            "DELETE FROM casbin_rule WHERE
510                    ptype = ? AND
511                    (v5 is NULL OR v5 = COALESCE(?,v5))",
512            pt,
513            field_values[0]
514        ))
515    } else if field_index == 4 {
516        Box::new(sqlx::query!(
517            "DELETE FROM casbin_rule WHERE
518                    ptype = ? AND
519                    (v4 is NULL OR v4 = COALESCE(?,v4)) AND
520                    (v5 is NULL OR v5 = COALESCE(?,v5))",
521            pt.to_string(),
522            field_values[0],
523            field_values[1]
524        ))
525    } else if field_index == 3 {
526        Box::new(sqlx::query!(
527            "DELETE FROM casbin_rule WHERE
528                    ptype = ? AND
529                    (v3 is NULL OR v3 = COALESCE(?,v3)) AND
530                    (v4 is NULL OR v4 = COALESCE(?,v4)) AND
531                    (v5 is NULL OR v5 = COALESCE(?,v5))",
532            pt,
533            field_values[0],
534            field_values[1],
535            field_values[2]
536        ))
537    } else if field_index == 2 {
538        Box::new(sqlx::query!(
539            "DELETE FROM casbin_rule WHERE
540                    ptype = ? AND
541                    (v2 is NULL OR v2 = COALESCE(?,v2)) AND
542                    (v3 is NULL OR v3 = COALESCE(?,v3)) AND
543                    (v4 is NULL OR v4 = COALESCE(?,v4)) AND
544                    (v5 is NULL OR v5 = COALESCE(?,v5))",
545            pt,
546            field_values[0],
547            field_values[1],
548            field_values[2],
549            field_values[3]
550        ))
551    } else if field_index == 1 {
552        Box::new(sqlx::query!(
553            "DELETE FROM casbin_rule WHERE
554                    ptype = ? AND
555                    (v1 is NULL OR v1 = COALESCE(?,v1)) AND
556                    (v2 is NULL OR v2 = COALESCE(?,v2)) AND
557                    (v3 is NULL OR v3 = COALESCE(?,v3)) AND
558                    (v4 is NULL OR v4 = COALESCE(?,v4)) AND
559                    (v5 is NULL OR v5 = COALESCE(?,v5))",
560            pt,
561            field_values[0],
562            field_values[1],
563            field_values[2],
564            field_values[3],
565            field_values[4]
566        ))
567    } else {
568        Box::new(sqlx::query!(
569            "DELETE FROM casbin_rule WHERE
570                    ptype = ? AND
571                    (v0 is NULL OR v0 = COALESCE(?,v0)) AND
572                    (v1 is NULL OR v1 = COALESCE(?,v1)) AND
573                    (v2 is NULL OR v2 = COALESCE(?,v2)) AND
574                    (v3 is NULL OR v3 = COALESCE(?,v3)) AND
575                    (v4 is NULL OR v4 = COALESCE(?,v4)) AND
576                    (v5 is NULL OR v5 = COALESCE(?,v5))",
577            pt,
578            field_values[0],
579            field_values[1],
580            field_values[2],
581            field_values[3],
582            field_values[4],
583            field_values[5]
584        ))
585    };
586
587    boxed_query
588        .execute(conn)
589        .await
590        .map(|n| MySqlQueryResult::rows_affected(&n) >= 1)
591        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
592}
593
594#[cfg(feature = "postgres")]
595pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
596    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
597        CasbinRule,
598        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
599    )
600    .fetch_all(conn)
601    .await
602    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
603
604    Ok(casbin_rule)
605}
606
607#[cfg(feature = "sqlite")]
608pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
609    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
610        CasbinRule,
611        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
612    )
613    .fetch_all(conn)
614    .await
615    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
616
617    Ok(casbin_rule)
618}
619
620#[cfg(feature = "mysql")]
621pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
622    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
623        CasbinRule,
624        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
625    )
626    .fetch_all(conn)
627    .await
628    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
629
630    Ok(casbin_rule)
631}
632
633#[cfg(feature = "postgres")]
634pub(crate) async fn load_filtered_policy(
635    conn: &ConnectionPool,
636    filter: &Filter<'_>,
637) -> Result<Vec<CasbinRule>> {
638    let (g_filter, p_filter) = filtered_where_values(filter);
639
640    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
641        CasbinRule,
642        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from  casbin_rule WHERE (
643            ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )
644        OR (
645            ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );
646            ",
647            g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
648            p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],)
649    .fetch_all(conn)
650    .await
651    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
652
653    Ok(casbin_rule)
654}
655
656#[cfg(feature = "sqlite")]
657pub(crate) async fn load_filtered_policy(
658    conn: &ConnectionPool,
659    filter: &Filter<'_>,
660) -> Result<Vec<CasbinRule>> {
661    let (g_filter, p_filter) = filtered_where_values(filter);
662
663    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
664        CasbinRule,
665        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from  casbin_rule WHERE (
666            ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )
667        OR (
668            ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );
669            ",
670            g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
671            p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],)
672        .fetch_all(conn)
673        .await
674        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
675
676    Ok(casbin_rule)
677}
678
679#[cfg(feature = "mysql")]
680pub(crate) async fn load_filtered_policy(
681    conn: &ConnectionPool,
682    filter: &Filter<'_>,
683) -> Result<Vec<CasbinRule>> {
684    let (g_filter, p_filter) = filtered_where_values(filter);
685
686    let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
687        CasbinRule,
688        "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from  casbin_rule WHERE (
689            ptype LIKE 'g%' AND v0 LIKE ? AND v1 LIKE ? AND v2 LIKE ? AND v3 LIKE ? AND v4 LIKE ? AND v5 LIKE ? )
690        OR (
691            ptype LIKE 'p%' AND v0 LIKE ? AND v1 LIKE ? AND v2 LIKE ? AND v3 LIKE ? AND v4 LIKE ? AND v5 LIKE ? );
692            ",
693            g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
694            p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],
695    )
696    .fetch_all(conn)
697    .await
698    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
699
700    Ok(casbin_rule)
701}
702
703fn filtered_where_values<'a>(filter: &Filter<'a>) -> ([&'a str; 6], [&'a str; 6]) {
704    let mut g_filter: [&'a str; 6] = ["%", "%", "%", "%", "%", "%"];
705    let mut p_filter: [&'a str; 6] = ["%", "%", "%", "%", "%", "%"];
706    for (idx, val) in filter.g.iter().enumerate() {
707        if val != &"" {
708            g_filter[idx] = val;
709        }
710    }
711    for (idx, val) in filter.p.iter().enumerate() {
712        if val != &"" {
713            p_filter[idx] = val;
714        }
715    }
716    (g_filter, p_filter)
717}
718
719#[cfg(feature = "postgres")]
720pub(crate) async fn save_policy(
721    conn: &ConnectionPool,
722    rules: Vec<NewCasbinRule<'_>>,
723) -> Result<()> {
724    let mut transaction = conn
725        .begin()
726        .await
727        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
728    sqlx::query!("DELETE FROM casbin_rule")
729        .execute(&mut *transaction)
730        .await
731        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
732    for rule in rules {
733        sqlx::query!(
734            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
735                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
736            rule.ptype,
737            rule.v0,
738            rule.v1,
739            rule.v2,
740            rule.v3,
741            rule.v4,
742            rule.v5
743        )
744        .execute(&mut *transaction)
745        .await
746        .and_then(|n| {
747            if PgQueryResult::rows_affected(&n) == 1 {
748                Ok(true)
749            } else {
750                Err(SqlxError::RowNotFound)
751            }
752        })
753        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
754    }
755    transaction
756        .commit()
757        .await
758        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
759    Ok(())
760}
761
762#[cfg(feature = "sqlite")]
763pub(crate) async fn save_policy(
764    conn: &ConnectionPool,
765    rules: Vec<NewCasbinRule<'_>>,
766) -> Result<()> {
767    let mut transaction = conn
768        .begin()
769        .await
770        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
771    sqlx::query!("DELETE FROM casbin_rule")
772        .execute(&mut *transaction)
773        .await
774        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
775    for rule in rules {
776        sqlx::query!(
777            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
778                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
779            rule.ptype,
780            rule.v0,
781            rule.v1,
782            rule.v2,
783            rule.v3,
784            rule.v4,
785            rule.v5
786        )
787        .execute(&mut *transaction)
788        .await
789        .and_then(|n| {
790            if SqliteQueryResult::rows_affected(&n) == 1 {
791                Ok(true)
792            } else {
793                Err(SqlxError::RowNotFound)
794            }
795        })
796        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
797    }
798    transaction
799        .commit()
800        .await
801        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
802    Ok(())
803}
804
805#[cfg(feature = "mysql")]
806pub(crate) async fn save_policy<'a>(
807    conn: &ConnectionPool,
808    rules: Vec<NewCasbinRule<'a>>,
809) -> Result<()> {
810    let mut transaction = conn
811        .begin()
812        .await
813        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
814    sqlx::query!("DELETE FROM casbin_rule")
815        .execute(&mut *transaction)
816        .await
817        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
818    for rule in rules {
819        sqlx::query!(
820            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
821                 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
822            rule.ptype,
823            rule.v0,
824            rule.v1,
825            rule.v2,
826            rule.v3,
827            rule.v4,
828            rule.v5
829        )
830        .execute(&mut *transaction)
831        .await
832        .and_then(|n| {
833            if MySqlQueryResult::rows_affected(&n) == 1 {
834                Ok(true)
835            } else {
836                Err(SqlxError::RowNotFound)
837            }
838        })
839        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
840    }
841    transaction
842        .commit()
843        .await
844        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
845    Ok(())
846}
847
848#[cfg(feature = "postgres")]
849pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
850    sqlx::query!(
851        "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
852                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
853        rule.ptype,
854        rule.v0,
855        rule.v1,
856        rule.v2,
857        rule.v3,
858        rule.v4,
859        rule.v5
860    )
861    .execute(conn)
862    .await
863    .map(|n| PgQueryResult::rows_affected(&n) == 1)
864    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
865
866    Ok(true)
867}
868
869#[cfg(feature = "sqlite")]
870pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
871    sqlx::query!(
872        "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
873                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
874        rule.ptype,
875        rule.v0,
876        rule.v1,
877        rule.v2,
878        rule.v3,
879        rule.v4,
880        rule.v5
881    )
882    .execute(conn)
883    .await
884    .map(|n| SqliteQueryResult::rows_affected(&n) == 1)
885    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
886
887    Ok(true)
888}
889
890#[cfg(feature = "mysql")]
891pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
892    sqlx::query!(
893        "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
894                 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
895        rule.ptype,
896        rule.v0,
897        rule.v1,
898        rule.v2,
899        rule.v3,
900        rule.v4,
901        rule.v5
902    )
903    .execute(conn)
904    .await
905    .map(|n| MySqlQueryResult::rows_affected(&n) == 1)
906    .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
907
908    Ok(true)
909}
910
911#[cfg(feature = "postgres")]
912pub(crate) async fn add_policies(
913    conn: &ConnectionPool,
914    rules: Vec<NewCasbinRule<'_>>,
915) -> Result<bool> {
916    let mut transaction = conn
917        .begin()
918        .await
919        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
920    for rule in rules {
921        sqlx::query!(
922            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
923                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
924            rule.ptype,
925            rule.v0,
926            rule.v1,
927            rule.v2,
928            rule.v3,
929            rule.v4,
930            rule.v5
931        )
932        .execute(&mut *transaction)
933        .await
934        .and_then(|n| {
935            if PgQueryResult::rows_affected(&n) == 1 {
936                Ok(true)
937            } else {
938                Err(SqlxError::RowNotFound)
939            }
940        })
941        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
942    }
943    transaction
944        .commit()
945        .await
946        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
947    Ok(true)
948}
949
950#[cfg(feature = "sqlite")]
951pub(crate) async fn add_policies(
952    conn: &ConnectionPool,
953    rules: Vec<NewCasbinRule<'_>>,
954) -> Result<bool> {
955    let mut transaction = conn
956        .begin()
957        .await
958        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
959    for rule in rules {
960        sqlx::query!(
961            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
962                 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
963            rule.ptype,
964            rule.v0,
965            rule.v1,
966            rule.v2,
967            rule.v3,
968            rule.v4,
969            rule.v5
970        )
971        .execute(&mut *transaction)
972        .await
973        .and_then(|n| {
974            if SqliteQueryResult::rows_affected(&n) == 1 {
975                Ok(true)
976            } else {
977                Err(SqlxError::RowNotFound)
978            }
979        })
980        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
981    }
982    transaction
983        .commit()
984        .await
985        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
986    Ok(true)
987}
988
989#[cfg(feature = "mysql")]
990pub(crate) async fn add_policies(
991    conn: &ConnectionPool,
992    rules: Vec<NewCasbinRule<'_>>,
993) -> Result<bool> {
994    let mut transaction = conn
995        .begin()
996        .await
997        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
998    for rule in rules {
999        sqlx::query!(
1000            "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
1001                 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
1002            rule.ptype,
1003            rule.v0,
1004            rule.v1,
1005            rule.v2,
1006            rule.v3,
1007            rule.v4,
1008            rule.v5
1009        )
1010        .execute(&mut *transaction)
1011        .await
1012        .and_then(|n| {
1013            if MySqlQueryResult::rows_affected(&n) == 1 {
1014                Ok(true)
1015            } else {
1016                Err(SqlxError::RowNotFound)
1017            }
1018        })
1019        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1020    }
1021    transaction
1022        .commit()
1023        .await
1024        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1025    Ok(true)
1026}
1027
1028#[cfg(feature = "postgres")]
1029pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1030    let mut transaction = conn
1031        .begin()
1032        .await
1033        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1034    sqlx::query!("DELETE FROM casbin_rule")
1035        .execute(&mut *transaction)
1036        .await
1037        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1038    transaction
1039        .commit()
1040        .await
1041        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1042    Ok(())
1043}
1044
1045#[cfg(feature = "sqlite")]
1046pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1047    let mut transaction = conn
1048        .begin()
1049        .await
1050        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1051    sqlx::query!("DELETE FROM casbin_rule")
1052        .execute(&mut *transaction)
1053        .await
1054        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1055    transaction
1056        .commit()
1057        .await
1058        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1059    Ok(())
1060}
1061
1062#[cfg(feature = "mysql")]
1063pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1064    let mut transaction = conn
1065        .begin()
1066        .await
1067        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1068    sqlx::query!("DELETE FROM casbin_rule")
1069        .execute(&mut *transaction)
1070        .await
1071        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1072    transaction
1073        .commit()
1074        .await
1075        .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1076    Ok(())
1077}
1078
1079fn normalize_casbin_rule(mut rule: Vec<String>) -> Vec<String> {
1080    rule.resize(6, String::new());
1081    rule
1082}
1083
1084fn normalize_casbin_rule_option(rule: Vec<String>) -> Vec<Option<String>> {
1085    let mut rule_with_option = rule
1086        .iter()
1087        .map(|x| match x.is_empty() {
1088            true => None,
1089            false => Some(x.clone()),
1090        })
1091        .collect::<Vec<Option<String>>>();
1092    rule_with_option.resize(6, None);
1093    rule_with_option
1094}