| 241 | } else { |
| 242 | BOLT_CHECK(isSpecialForm()); |
| 243 | deterministic_ = true; |
| 244 | } |
| 245 | |
| 246 | for (auto& input : inputs_) { |
| 247 | deterministic_ &= input->deterministic_; |
| 248 | } |
| 249 | |
| 250 | // (2) Compute distinctFields_ and multiplyReferencedFields_. |
| 251 | computeDistinctFields(); |
| 252 | |
| 253 | // (3) Compute propagatesNulls_. |
| 254 | // propagatesNulls_ is true iff a null in any of the columns this |
| 255 | // depends on makes the Expr null. |
| 256 | if (isSpecialForm() && !is<ConstantExpr>() && !is<FieldReference>() && |
| 257 | !is<CastExpr>()) { |
| 258 | as<SpecialForm>()->computePropagatesNulls(); |
| 259 | } else { |
| 260 | if (vectorFunction_ && !vectorFunction_->isDefaultNullBehavior()) { |
| 261 | propagatesNulls_ = false; |
| 262 | } else { |
| 263 | // Logic for handling default-null vector functions. |
| 264 | // cast, constant and fieldReference expressions act as vector functions |
| 265 | // with default null behavior. |
| 266 | |
| 267 | // If the function has default null behavior, the Expr propagates nulls if |
| 268 | // the set of fields null-propagating arguments depend on is a superset of |
| 269 | // the fields non null-propagating arguments depend on. |
| 270 | std::unordered_set<FieldReference*> nullPropagating, nonNullPropagating; |
| 271 | for (auto& input : inputs_) { |
| 272 | if (input->propagatesNulls_) { |
| 273 | nullPropagating.insert( |
| 274 | input->distinctFields_.begin(), input->distinctFields_.end()); |
| 275 | } else { |
| 276 | nonNullPropagating.insert( |
| 277 | input->distinctFields_.begin(), input->distinctFields_.end()); |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | // propagatesNulls_ is true if nonNullPropagating is subset of |
| 282 | // nullPropagating. |
| 283 | propagatesNulls_ = true; |
| 284 | for (auto* field : nonNullPropagating) { |
| 285 | if (!nullPropagating.count(field)) { |
| 286 | propagatesNulls_ = false; |
| 287 | break; |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | for (auto& input : inputs_) { |
| 294 | if (isSameFields(distinctFields_, input->distinctFields_)) { |
| 295 | input->sameAsParentDistinctFields_ = true; |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // (5) Compute hasConditionals_. |
| 300 | hasConditionals_ = hasConditionals(this); |
no test coverage detected