class HumanQL::TreeNormalizer
Normalizes and imposes various limitations on query abstract syntax trees (ASTs).
Constants
- EMPTY_STACK
Attributes
Allow nested :not (in other words, double negatives)? Default: false -> nested :not nodes are removed.
Allow nested scopes? Default: false -> nested scope nodes are removed.
Allow SCOPE within :not?
-
If set to `:invert` normalizes `[:not, ['SCOPE', 'a']]` to `['SCOPE', [:not, 'a']]`.
-
If set to `false`, the nested scope node is removed.
-
For either :invert or false, the scope node is otherwise removed if found below a :not node.
Default: :invert
Allow only scopes combined with :and condition? Default: false
Allow scope at root or first level only? Default: false
Does a scope count as a constraint? Default: true -> a scope is a constraint if its argument is a constraint. If it depends on the scope, you can override scope_can_constrain?
with this logic.
Allow unconstrained :not? Queries containing an unconstrained :not may be costly to execute. If false the unconstrained :not will be removed.
A :not node is considered “constrained” if it has an :and ancestor with at least one constraint argument. A constraint argument is a term, phrase, or :and node matching this same criteria, or an :or node where all arguments match this criteria. See also scope_can_constrain
. Default: true
Public Class Methods
Construct given options that are applied via same name setters on self.
# File lib/human-ql/tree_normalizer.rb, line 69 def initialize(opts = {}) @nested_scope = false @nested_not = false @unconstrained_not = true @scope_can_constrain = true @scope_at_top_only = false @scope_and_only = false @not_scope = :invert opts.each do |name,val| send(name.to_s + '=', val) end end
Public Instance Methods
Return a new normalized AST from the given AST root node.
# File lib/human-ql/tree_normalizer.rb, line 84 def normalize(node) node = normalize_1(node, EMPTY_STACK, @unconstrained_not) if (@not_scope != true) || @scope_and_only || @scope_at_top_only node = normalize_2(node, EMPTY_STACK) end node end
Protected Instance Methods
Return true if node is a valid constraint
# File lib/human-ql/tree_normalizer.rb, line 101 def constraint?(node) op,*args = node if ! node.is_a?(Array) true elsif args.empty? false else case op when :and args.any? { |a| constraint?(a) } when :or args.all? { |a| constraint?(a) } when :phrase true when String scope_can_constrain?(op) && constraint?(args.first) else false end end end
# File lib/human-ql/tree_normalizer.rb, line 94 def scope_can_constrain?(scope) @scope_can_constrain end