github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/volatility.go (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     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, included in the file
     9  // licenses/APL.txt.
    10  
    11  package tree
    12  
    13  import "github.com/cockroachdb/errors"
    14  
    15  // Volatility indicates whether the result of a function is dependent *only*
    16  // on the values of its explicit arguments, or can change due to outside factors
    17  // (such as parameter variables or table contents).
    18  //
    19  // The values are ordered with smaller values being strictly more restrictive
    20  // than larger values.
    21  //
    22  // NOTE: functions having side-effects, such as setval(),
    23  // must be labeled volatile to ensure they will not get optimized away,
    24  // even if the actual return value is not changeable.
    25  type Volatility int8
    26  
    27  const (
    28  	// VolatilityLeakProof means that the operator cannot modify the database, the
    29  	// transaction state, or any other state. It cannot depend on configuration
    30  	// settings and is guaranteed to return the same results given the same
    31  	// arguments in any context. In addition, no information about the arguments
    32  	// is conveyed except via the return value. Any function that might throw an
    33  	// error depending on the values of its arguments is not leak-proof.
    34  	//
    35  	// USE THIS WITH CAUTION! The optimizer might call operators that are leak
    36  	// proof on inputs that they wouldn't normally be called on (e.g. pulling
    37  	// expressions out of a CASE). In the future, they may even run on rows that
    38  	// the user doesn't have permission to access.
    39  	//
    40  	// Note: VolatilityLeakProof is strictly stronger than VolatilityImmutable. In
    41  	// principle it could be possible to have leak-proof stable or volatile
    42  	// functions (perhaps now()); but this is not useful in practice as very few
    43  	// operators are marked leak-proof.
    44  	// Examples: integer comparison.
    45  	VolatilityLeakProof Volatility = 1 + iota
    46  	// VolatilityImmutable means that the operator cannot modify the database, the
    47  	// transaction state, or any other state. It cannot depend on configuration
    48  	// settings and is guaranteed to return the same results given the same
    49  	// arguments in any context. Immutable operators can be constant folded.
    50  	// Examples: log, from_json.
    51  	VolatilityImmutable
    52  	// VolatilityStable means that the operator cannot modify the database or the
    53  	// transaction state and is guaranteed to return the same results given the
    54  	// same arguments whenever it is evaluated within the same statement. Multiple
    55  	// calls to a stable operator can be optimized to a single call.
    56  	// Examples: current_timestamp, current_date.
    57  	VolatilityStable
    58  	// VolatilityVolatile means that the operator can do anything, including
    59  	// modifying database state.
    60  	// Examples: random, crdb_internal.force_error, nextval.
    61  	VolatilityVolatile
    62  )
    63  
    64  // String returns the byte representation of Volatility as a string.
    65  func (v Volatility) String() string {
    66  	switch v {
    67  	case VolatilityLeakProof:
    68  		return "leak-proof"
    69  	case VolatilityImmutable:
    70  		return "immutable"
    71  	case VolatilityStable:
    72  		return "stable"
    73  	case VolatilityVolatile:
    74  		return "volatile"
    75  	default:
    76  		return "invalid"
    77  	}
    78  }
    79  
    80  // ToPostgres returns the postgres "provolatile" string ("i" or "s" or "v") and
    81  // the "proleakproof" flag.
    82  func (v Volatility) ToPostgres() (provolatile string, proleakproof bool) {
    83  	switch v {
    84  	case VolatilityLeakProof:
    85  		return "i", true
    86  	case VolatilityImmutable:
    87  		return "i", false
    88  	case VolatilityStable:
    89  		return "s", false
    90  	case VolatilityVolatile:
    91  		return "v", false
    92  	default:
    93  		panic(errors.AssertionFailedf("invalid volatility %s", v))
    94  	}
    95  }
    96  
    97  // VolatilityFromPostgres returns a Volatility that matches the postgres
    98  // provolatile/proleakproof settings.
    99  func VolatilityFromPostgres(provolatile string, proleakproof bool) (Volatility, error) {
   100  	switch provolatile {
   101  	case "i":
   102  		if proleakproof {
   103  			return VolatilityLeakProof, nil
   104  		}
   105  		return VolatilityImmutable, nil
   106  	case "s":
   107  		return VolatilityStable, nil
   108  	case "v":
   109  		return VolatilityVolatile, nil
   110  	default:
   111  		return 0, errors.AssertionFailedf("invalid provolatile %s", provolatile)
   112  	}
   113  }