Class: ActiveRecord::Refined::AST::JsonAggregate
- Includes:
- ComputedJson, JsonComparable, Predications, Windowing
- Defined in:
- lib/active_record/refined/ast.rb
Overview
Rows gathered into one JSON document: json_arrayagg collects a value from each row into an array, json_objectagg a key and a value into an object. Every adapter has the pair under a name of its own; what PostgreSQL gets is the jsonb one, whose documents the other JSON operations here read.
Constant Summary collapse
- NAMES =
The standard names, which are also the DSL's own and MySQL's, serve any adapter the table does not list.
{ arrayagg: { sqlite: "json_group_array", postgresql: "jsonb_agg" }, objectagg: { sqlite: "json_group_object", postgresql: "jsonb_object_agg" }, }.freeze
Instance Attribute Summary collapse
-
#condition ⇒ Object
readonly
Returns the value of attribute condition.
-
#kind ⇒ Object
readonly
Returns the value of attribute kind.
-
#operands ⇒ Object
readonly
Returns the value of attribute operands.
Instance Method Summary collapse
-
#check_window(model) ⇒ Object
MariaDB takes every other aggregate as a window function, but not these two; Over asks here before writing one.
- #filter(condition = nil, &block) ⇒ Object
-
#initialize(kind, operands, condition: nil) ⇒ JsonAggregate
constructor
A new instance of JsonAggregate.
- #to_arel(table, model) ⇒ Object
Methods included from Windowing
Methods included from ComputedJson
Methods included from JsonComparable
#between?, #in?, #not_between?, #not_in?, #~
Methods included from Predications
#!=, #!~, #<, #<=, #==, #=~, #>, #>=, #between?, #bury, #casecmp?, #contains?, #dig, #dig_text, #distinct_from?, #end_with?, #except, #false?, #ilike?, #in?, #include?, #intersect?, #key?, #keys, #like?, #member?, #not_between?, #not_distinct_from?, #not_false?, #not_ilike?, #not_in?, #not_like?, #not_null?, #not_true?, #null?, #start_with?, #subset?, #superset?, #true?, #when
Methods inherited from Node
Constructor Details
#initialize(kind, operands, condition: nil) ⇒ JsonAggregate
Returns a new instance of JsonAggregate.
1553 1554 1555 1556 1557 |
# File 'lib/active_record/refined/ast.rb', line 1553 def initialize(kind, operands, condition: nil) @kind = kind @operands = operands @condition = condition end |
Instance Attribute Details
#condition ⇒ Object (readonly)
Returns the value of attribute condition.
1551 1552 1553 |
# File 'lib/active_record/refined/ast.rb', line 1551 def condition @condition end |
#kind ⇒ Object (readonly)
Returns the value of attribute kind.
1551 1552 1553 |
# File 'lib/active_record/refined/ast.rb', line 1551 def kind @kind end |
#operands ⇒ Object (readonly)
Returns the value of attribute operands.
1551 1552 1553 |
# File 'lib/active_record/refined/ast.rb', line 1551 def operands @operands end |
Instance Method Details
#check_window(model) ⇒ Object
MariaDB takes every other aggregate as a window function, but not these two; Over asks here before writing one.
1566 1567 1568 1569 1570 1571 |
# File 'lib/active_record/refined/ast.rb', line 1566 def check_window(model) return unless AST.adapter_family(model) == :mysql return unless model.with_connection { |connection| connection.mariadb? } raise NotImplementedError, "#{json_source} over a window has no equivalent on MariaDB" end |
#filter(condition = nil, &block) ⇒ Object
1559 1560 1561 1562 |
# File 'lib/active_record/refined/ast.rb', line 1559 def filter(condition = nil, &block) JsonAggregate.new(kind, operands, condition: Case.argument(:filter, condition, block)) end |
#to_arel(table, model) ⇒ Object
1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 |
# File 'lib/active_record/refined/ast.rb', line 1573 def to_arel(table, model) family = AST.adapter_family(model) call = Arel::Nodes::NamedFunction.new( NAMES.fetch(kind).fetch(family) { "JSON_#{kind.to_s.upcase}" }, operands.map { |operand| to_arel_argument(operand, table, model) }) return call unless condition # The CASE that stands in for FILTER elsewhere hands the aggregate # a NULL for every row the condition misses, and these two keep a # NULL -- as JSON null -- rather than passing over it. if family == :mysql raise NotImplementedError, "#{json_source}.filter has no equivalent on " \ "#{model.connection_db_config.adapter}; a CASE would leave a " \ "null in the document for every row it drops" end call.filter(condition.to_arel(table, model)) end |