Optimisation - only loop over document fields when processing PERMISSIONS clauses (#1890)

This commit is contained in:
Tobie Morgan Hitchcock 2023-04-30 00:23:19 +01:00 committed by GitHub
parent 1e8903b699
commit c7e3b927ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 44 deletions

View file

@ -13,31 +13,31 @@ use std::sync::Arc;
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Options { pub struct Options {
// Currently selected NS /// Currently selected NS
pub ns: Option<Arc<str>>, pub ns: Option<Arc<str>>,
// Currently selected DB /// Currently selected DB
pub db: Option<Arc<str>>, pub db: Option<Arc<str>>,
// Connection authentication data /// Connection authentication data
pub auth: Arc<Auth>, pub auth: Arc<Auth>,
// Approximately how large is the current call stack? /// Approximately how large is the current call stack?
dive: u8, dive: u8,
// Whether live queries are allowed? /// Whether live queries are allowed?
pub live: bool, pub live: bool,
// Should we force tables/events to re-run? /// Should we force tables/events to re-run?
pub force: bool, pub force: bool,
// Should we run permissions checks? /// Should we run permissions checks?
pub perms: bool, pub perms: bool,
// Should we error if tables don't exist? /// Should we error if tables don't exist?
pub strict: bool, pub strict: bool,
// Should we process field queries? /// Should we process field queries?
pub fields: bool, pub fields: bool,
// Should we process event queries? /// Should we process event queries?
pub events: bool, pub events: bool,
// Should we process table queries? /// Should we process table queries?
pub tables: bool, pub tables: bool,
// Should we process index queries? /// Should we process index queries?
pub indexes: bool, pub indexes: bool,
// Should we process function futures? /// Should we process function futures?
pub futures: bool, pub futures: bool,
} }

View file

@ -14,30 +14,33 @@ impl<'a> Document<'a> {
txn: &Transaction, txn: &Transaction,
stm: &Statement<'_>, stm: &Statement<'_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Check permission clause // Check if this record exists
if opt.perms && opt.auth.perms() && self.id.is_some() { if self.id.is_some() {
// Get the table // Should we run permissions checks?
let tb = self.tb(opt, txn).await?; if opt.perms && opt.auth.perms() {
// Get the permission clause // Get the table
let perms = if stm.is_delete() { let tb = self.tb(opt, txn).await?;
&tb.permissions.delete // Get the permission clause
} else if stm.is_select() { let perms = if stm.is_delete() {
&tb.permissions.select &tb.permissions.delete
} else if self.is_new() { } else if stm.is_select() {
&tb.permissions.create &tb.permissions.select
} else { } else if self.is_new() {
&tb.permissions.update &tb.permissions.create
}; } else {
// Match the permission clause &tb.permissions.update
match perms { };
Permission::None => return Err(Error::Ignore), // Process the table permissions
Permission::Full => return Ok(()), match perms {
Permission::Specific(e) => { Permission::None => return Err(Error::Ignore),
// Disable permissions Permission::Full => return Ok(()),
let opt = &opt.perms(false); Permission::Specific(e) => {
// Process the PERMISSION clause // Disable permissions
if !e.compute(ctx, opt, txn, Some(&self.current)).await?.is_truthy() { let opt = &opt.perms(false);
return Err(Error::Ignore); // Process the PERMISSION clause
if !e.compute(ctx, opt, txn, Some(&self.current)).await?.is_truthy() {
return Err(Error::Ignore);
}
} }
} }
} }

View file

@ -55,13 +55,13 @@ impl<'a> Document<'a> {
}?; }?;
// Check if this record exists // Check if this record exists
if self.id.is_some() { if self.id.is_some() {
// Loop through all field statements // Should we run permissions checks?
for fd in self.fd(opt, txn).await?.iter() { if opt.perms && opt.auth.perms() {
// Loop over each field in document // Loop through all field statements
for k in out.each(&fd.name).iter() { for fd in self.fd(opt, txn).await?.iter() {
// Check for a PERMISSIONS clause // Loop over each field in document
if opt.perms && opt.auth.perms() { for k in out.each(&fd.name).iter() {
// Process field permissions // Process the field permissions
match &fd.permissions.select { match &fd.permissions.select {
Permission::Full => (), Permission::Full => (),
Permission::None => out.del(ctx, opt, txn, k).await?, Permission::None => out.del(ctx, opt, txn, k).await?,