|
| 1 | +--- |
| 2 | +{ |
| 3 | + "title": "Conditional Functions Overview", |
| 4 | + "language": "en", |
| 5 | + "description": "Conditional functions are built-in functions used to perform conditional logic and branching in SQL queries." |
| 6 | +} |
| 7 | +--- |
| 8 | + |
| 9 | +# Conditional Functions Overview |
| 10 | + |
| 11 | +Conditional functions are built-in functions used to perform conditional logic and branching in SQL queries. They help execute different operations based on specified conditions, such as selecting values, handling NULL values, and performing case-based logic. |
| 12 | + |
| 13 | +## Vectorized Execution and Conditional Functions |
| 14 | + |
| 15 | +Doris is a vectorized execution engine. However, conditional functions may behave in ways that seem counterintuitive. |
| 16 | + |
| 17 | +Consider the following example: |
| 18 | + |
| 19 | +```sql |
| 20 | +mysql> set enable_strict_cast = true; |
| 21 | +Query OK, 0 rows affected (0.00 sec) |
| 22 | + |
| 23 | +mysql> select count( |
| 24 | + -> if(number < 128 , |
| 25 | + -> cast(number as tinyint), |
| 26 | + -> cast(number as String)) |
| 27 | + -> ) from numbers("number" = "300"); |
| 28 | +ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[INVALID_ARGUMENT]Value 128 out of range for type tinyint |
| 29 | +``` |
| 30 | + |
| 31 | +In this example, even though we only cast to `tinyint` when `number < 128` in the `if` function, an error still occurs. This is because of how conditional functions like `if(cond, colA, colB)` were traditionally executed: |
| 32 | + |
| 33 | +1. First, both `colA` and `colB` are fully computed |
| 34 | +2. Then, based on the value of `cond`, the corresponding result is selected and returned |
| 35 | + |
| 36 | +So even if `colA`'s value is not actually used in practice, since `colA` is fully computed, it will still trigger an error. |
| 37 | + |
| 38 | +Functions like `if`, `ifnull`, `case`, and `coalesce` have similar behavior. |
| 39 | + |
| 40 | +Note that functions like `LEAST` do not have this issue because they inherently need to compute all parameters to compare values. |
| 41 | + |
| 42 | +## Short-Circuit Evaluation |
| 43 | + |
| 44 | +In Doris 4.0, we improved the execution logic of conditional functions to allow short-circuit evaluation. |
| 45 | + |
| 46 | +```sql |
| 47 | +mysql> set short_circuit_evaluation = true; |
| 48 | +Query OK, 0 rows affected (0.00 sec) |
| 49 | + |
| 50 | +mysql> select count( |
| 51 | + -> if(number < 128 , |
| 52 | + -> cast(number as tinyint), |
| 53 | + -> cast(number as String)) |
| 54 | + -> ) from numbers("number" = "300"); |
| 55 | ++-------------------------------------------------------------------------+ |
| 56 | +| count(if(number < 128, cast(number as tinyint), cast(number as String)))| |
| 57 | ++-------------------------------------------------------------------------+ |
| 58 | +| 300 | |
| 59 | ++-------------------------------------------------------------------------+ |
| 60 | +``` |
| 61 | + |
| 62 | +With short-circuit evaluation enabled, functions like `if`, `ifnull`, `case`, and `coalesce` can avoid unnecessary computations in many scenarios, thus preventing errors and improving performance. |
| 63 | + |
| 64 | +### Enabling Short-Circuit Evaluation |
| 65 | + |
| 66 | +To enable short-circuit evaluation, set the session variable: |
| 67 | + |
| 68 | +```sql |
| 69 | +SET short_circuit_evaluation = true; |
| 70 | +``` |
| 71 | + |
| 72 | +### Benefits of Short-Circuit Evaluation |
| 73 | + |
| 74 | +1. **Error Prevention**: Avoids executing branches that would cause errors when conditions exclude them |
| 75 | +2. **Performance Improvement**: Reduces unnecessary computations by only evaluating branches that are actually needed |
| 76 | +3. **More Intuitive Behavior**: Makes conditional functions behave more like traditional programming language conditionals |
| 77 | + |
| 78 | +## Common Conditional Functions |
| 79 | + |
| 80 | +Common conditional functions that benefit from short-circuit evaluation include: |
| 81 | + |
| 82 | +- `IF`: Returns one of two values based on a condition |
| 83 | +- `IFNULL`: Returns the first argument if it's not NULL, otherwise returns the second argument |
| 84 | +- `CASE`: Provides multiple conditional branches similar to switch-case statements |
| 85 | +- `COALESCE`: Returns the first non-NULL value from a list of arguments |
| 86 | +- `NULLIF`: Returns NULL if two arguments are equal, otherwise returns the first argument |
| 87 | + |
| 88 | +For detailed information about each function, please refer to their respective documentation pages. |
0 commit comments