variadic_outer_joins.jq 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. #
  10. # variadic_outer_joins.jq — finds and analyzes outer join stacks in HIR (RAW PLANs)
  11. include "defs";
  12. def is_left_or_inner_join:
  13. type == "object"
  14. and has("Join")
  15. and (.Join.kind | . == "LeftOuter" or . == "Inner")
  16. ;
  17. def is_join_stack:
  18. is_left_or_inner_join
  19. and (.Join.left | is_left_or_inner_join)
  20. and (.Join.left.Join.left | is_left_or_inner_join)
  21. ;
  22. def unstacked_children:
  23. if is_left_or_inner_join
  24. then [.Join.left | unstacked_children[] , .Join.right | unstacked_children[] ]
  25. else [.]
  26. end
  27. ;
  28. def maximal_stacks:
  29. if is_join_stack
  30. then ., # return this stack of joins...
  31. (unstacked_children | maximal_stacks) # ...and search the children that aren't themselves stacked
  32. else .[]? | maximal_stacks
  33. end
  34. ;
  35. def stack_info:
  36. if is_left_or_inner_join
  37. then .Join.kind as $kind | .Join.left | stack_info | (getpath([$kind]) |= .+1 | .total |= .+1)
  38. else { "LeftOuter": 0, "Inner": 0, "total": 0 }
  39. end
  40. ;
  41. def collect_predicates:
  42. if has("CallVariadic")
  43. and .CallVariadic.func == "And"
  44. then .CallVariadic.exprs
  45. else [.]
  46. end
  47. ;
  48. def literal_true:
  49. has("Literal")
  50. and .Literal[0].data == 2 # null encoding?
  51. and .Literal[1].scalar_type == "Bool"
  52. ;
  53. def is_column_ref:
  54. has("Column") and .Column.level == 0
  55. ;
  56. def simple_eq:
  57. has("CallBinary")
  58. and .CallBinary.func == "Eq"
  59. and (.CallBinary.expr1 | is_column_ref)
  60. and (.CallBinary.expr2 | is_column_ref)
  61. ;
  62. def is_column_ref_or_func_of_column_refs:
  63. is_column_ref
  64. or (has("CallUnary") and (.CallUnary.expr | is_column_ref))
  65. or (has("CallBinary") and ((.CallBinary.expr1 | is_column_ref) or (.CallBinary.expr2 | is_column_ref))) # what else do we want to allow?
  66. or (has("CallVariadic") and (.CallVariadic.exprs | any(is_column_ref)))
  67. ;
  68. def complex_eq:
  69. has("CallBinary")
  70. and .CallBinary.func == "Eq"
  71. and (.CallBinary.expr1 | is_column_ref_or_func_of_column_refs)
  72. and (.CallBinary.expr2 | is_column_ref_or_func_of_column_refs)
  73. ;
  74. def join_predicates:
  75. if is_left_or_inner_join
  76. then [(.Join.on | collect_predicates[]),
  77. (.Join.left | join_predicates[]),
  78. (.Join.right | join_predicates[])
  79. ]
  80. else []
  81. end
  82. ;
  83. def compute_predicate_info:
  84. join_predicates
  85. | reduce .[] as $pred
  86. ({"literal_true": 0, "simple_eq": 0, "complex_eq": 0 };
  87. if $pred | literal_true
  88. then .literal_true += 1
  89. elif $pred | simple_eq
  90. then .simple_eq += 1
  91. elif $pred | complex_eq
  92. then .complex_eq += 1
  93. else .
  94. end)
  95. ;
  96. maximal_stacks | values | { "file": input_filename, "size": . | stack_info, "predicates": . | compute_predicate_info }