pub struct LiteralConstraints;
Expand description

Convert literal constraints into IndexedFilter joins.

Implementations§

source§

impl LiteralConstraints

source

fn action( &self, relation: &mut MirRelationExpr, transform_ctx: &mut TransformCtx<'_>, ) -> Result<(), TransformError>

source

fn detect_literal_constraints( mfp: &MapFilterProject, get_id: GlobalId, transform_ctx: &mut TransformCtx<'_>, ) -> Option<(GlobalId, Vec<MirScalarExpr>, Vec<Row>)>

Detects literal constraints in an MFP on top of a Get of id, and a matching index that can be used to speed up the Filter of the MFP.

For example, if there is an index on (f1, f2), and the Filter is (f1 = 3 AND f2 = 5) OR (f1 = 7 AND f2 = 9), it returns Some([f1, f2], [[3,5], [7,9]]).

We can use an index if each argument of the OR includes a literal constraint on each of the key fields of the index. Extra predicates inside the OR arguments are ok.

Returns (idx_id, idx_key, values to lookup in the index).

source

fn remove_literal_constraints( mfp: &mut MapFilterProject, key: &Vec<MirScalarExpr>, ) -> bool

Removes the expressions that LiteralConstraints::detect_literal_constraints found, if possible. Returns whether it removed anything. For example, if the key of the detected literal constraint is just f1, and we have the expression (f1 = 3 AND f2 = 5) OR (f1 = 7 AND f2 = 5), then this modifies it to f2 = 5. However, if OR branches differ in their non-key parts, then we cannot remove the literal constraint. For example, (f1 = 3 AND f2 = 5) OR (f1 = 7 AND f2 = 555), then we cannot remove the f1 parts, because then the filter wouldn’t know whether to check f2 = 5 or f2 = 555.

source

fn remove_impossible_or_args( mfp: &mut MapFilterProject, ) -> Result<bool, RecursionLimitError>

  1. Removes such OR args in which there are contradicting literal constraints.
  2. Also, if an OR arg doesn’t have any contradiction, this fn just deduplicates the AND arg list of that OR arg. (Might additionally sort all AND arg lists.)

Returns whether it performed any removal or deduplication.

Example for 1: <arg1> OR (a = 5 AND a = 5 AND a = 8) OR <arg3> –> <arg1> OR <arg3>

Example for 2: <arg1> OR (a = 5 AND a = 5 AND b = 8) OR <arg3> –> <arg1> OR (a = 5 AND b = 8) OR <arg3>

source

fn get_or_args(mfp: &MapFilterProject) -> Vec<MirScalarExpr>

Returns the arguments of the predicate’s top-level OR as a Vec. If there is no top-level OR, then interpret the predicate as a 1-arg OR, i.e., return a 1-element Vec.

Assumes that LiteralConstraints::list_of_predicates_to_and_of_predicates has already run.

source

fn inline_literal_constraints(mfp: &mut MapFilterProject)

Makes the job of LiteralConstraints::detect_literal_constraints easier by undoing some CSE to reconstruct literal constraints.

source

fn list_of_predicates_to_and_of_predicates(mfp: &mut MapFilterProject)

MFPs have a Vec of predicates [p1, p2, ...], which logically represents p1 AND p2 AND .... This function performs this conversion. Note that it might create a variadic AND with 0 or 1 args, so the resulting predicate Vec always has exactly 1 element.

source

fn canonicalize_predicates( mfp: &mut MapFilterProject, relation: &MirRelationExpr, )

Call mz_expr::canonicalize::canonicalize_predicates on each of the predicates in the MFP.

source

fn distribute_and_over_or( mfp: &mut MapFilterProject, ) -> Result<(), RecursionLimitError>

Distribute AND over OR + do flatten_and_or until fixed point. This effectively converts to disjunctive normal form (DNF) (i.e., an OR of ANDs), because MirScalarExpr::reduce did Demorgans and double-negation-elimination. So after MirScalarExpr::reduce, we get here a tree of AND/OR nodes. A distribution step lifts an OR up the tree by 1 level, and a MirScalarExpr::flatten_associative merges two ORs that are at adjacent levels, so eventually we’ll end up with just one OR that is at the top of the tree, with ANDs below it. For example: (a || b) && (c || d) -> ((a || b) && c) || ((a || b) && d) -> (a && c) || (b && c) || (a && d) || (b && d) (This is a variadic OR with 4 arguments.)

Example: User wrote WHERE (a,b) IN ((1,2), (1,4), (8,5)), from which MirScalarExpr::undistribute_and_or made this before us: (#0 = 1 AND (#1 = 2 OR #1 = 4)) OR (#0 = 8 AND #1 = 5) And now we distribute the first AND over the first OR in 2 steps: First to ((#0 = 1 AND #1 = 2) OR (#0 = 1 AND #1 = 4)) OR (#0 = 8 AND #1 = 5) then MirScalarExpr::flatten_associative: (#0 = 1 AND #1 = 2) OR (#0 = 1 AND #1 = 4) OR (#0 = 8 AND #1 = 5)

Note that MirScalarExpr::undistribute_and_or is not exactly an inverse to this because

  1. it can undistribute both AND over OR and OR over AND.
  2. it cannot always undo the distribution, because an expression might have multiple overlapping undistribution opportunities, see comment there.
source

fn unary_and(mfp: &mut MapFilterProject)

For each of the arguments of the top-level OR (if no top-level OR, then interpret the whole expression as a 1-arg OR, see LiteralConstraints::get_or_args), check if it’s an AND, and if not, then wrap it in a 1-arg AND.

source

fn predicates_size(mfp: &MapFilterProject) -> usize

Trait Implementations§

source§

impl Debug for LiteralConstraints

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Transform for LiteralConstraints

source§

fn transform( &self, relation: &mut MirRelationExpr, ctx: &mut TransformCtx<'_>, ) -> Result<(), TransformError>

Transform a relation into a functionally equivalent relation.
source§

fn debug(&self) -> String

A string describing the transform. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, U> CastInto<U> for T
where U: CastFrom<T>,

source§

fn cast_into(self) -> U

Performs the cast.
source§

impl<T> Conv for T

source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
source§

impl<T> FmtForward for T

source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FutureExt for T

source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
source§

impl<T, U> OverrideFrom<Option<&T>> for U
where U: OverrideFrom<T>,

source§

fn override_from(self, layer: &Option<&T>) -> U

Override the configuration represented by Self with values from the given layer.
source§

impl<T> Pipe for T
where T: ?Sized,

source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<P, R> ProtoType<R> for P
where R: RustType<P>,

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<'a, S, T> Semigroup<&'a S> for T
where T: Semigroup<S>,

source§

fn plus_equals(&mut self, rhs: &&'a S)

The method of std::ops::AddAssign, for types that do not implement AddAssign.
source§

impl<T> Tap for T

source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
source§

impl<T> TryConv for T

source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,