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

     1  // Copyright 2018 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 sql
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"strings"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/base"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    22  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    23  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    24  )
    25  
    26  // TestFuncNull execs all builtin funcs with various kinds of NULLs,
    27  // attempting to induce a panic.
    28  func TestFuncNull(t *testing.T) {
    29  	defer leaktest.AfterTest(t)()
    30  
    31  	s, db, _ := serverutils.StartServer(t, base.TestServerArgs{})
    32  	ctx := context.Background()
    33  	defer s.Stopper().Stop(ctx)
    34  
    35  	run := func(t *testing.T, q string) {
    36  		rows, err := db.QueryContext(ctx, q)
    37  		if err == nil {
    38  			rows.Close()
    39  		}
    40  	}
    41  
    42  	for _, name := range builtins.AllBuiltinNames {
    43  		switch strings.ToLower(name) {
    44  		case "crdb_internal.force_panic", "crdb_internal.force_log_fatal", "pg_sleep":
    45  			continue
    46  		}
    47  		_, variations := builtins.GetBuiltinProperties(name)
    48  		for _, builtin := range variations {
    49  			// Untyped NULL.
    50  			{
    51  				var sb strings.Builder
    52  				fmt.Fprintf(&sb, "SELECT %s(", name)
    53  				for i := range builtin.Types.Types() {
    54  					if i > 0 {
    55  						sb.WriteString(", ")
    56  					}
    57  					sb.WriteString("NULL")
    58  				}
    59  				sb.WriteString(")")
    60  				run(t, sb.String())
    61  			}
    62  			// Typed NULL.
    63  			{
    64  				var sb strings.Builder
    65  				fmt.Fprintf(&sb, "SELECT %s(", name)
    66  				for i, typ := range builtin.Types.Types() {
    67  					if i > 0 {
    68  						sb.WriteString(", ")
    69  					}
    70  					fmt.Fprintf(&sb, "NULL::%s", typ)
    71  				}
    72  				sb.WriteString(")")
    73  				run(t, sb.String())
    74  			}
    75  			// NULL that the type system can't (at least not yet?) know is NULL.
    76  			{
    77  				var sb strings.Builder
    78  				fmt.Fprintf(&sb, "SELECT %s(", name)
    79  				for i, typ := range builtin.Types.Types() {
    80  					if i > 0 {
    81  						sb.WriteString(", ")
    82  					}
    83  					fmt.Fprintf(&sb, "(SELECT NULL)::%s", typ)
    84  				}
    85  				sb.WriteString(")")
    86  				run(t, sb.String())
    87  			}
    88  			// For array types, make an array with a NULL.
    89  			{
    90  				var sb strings.Builder
    91  				fmt.Fprintf(&sb, "SELECT %s(", name)
    92  				hasArray := false
    93  				for i, typ := range builtin.Types.Types() {
    94  					if i > 0 {
    95  						sb.WriteString(", ")
    96  					}
    97  					if typ.Family() == types.ArrayFamily {
    98  						hasArray = true
    99  						if typ.ArrayContents().Family() == types.AnyFamily {
   100  							fmt.Fprintf(&sb, "ARRAY[NULL]::STRING[]")
   101  						} else {
   102  							fmt.Fprintf(&sb, "ARRAY[NULL]::%s", typ)
   103  						}
   104  					} else {
   105  						fmt.Fprintf(&sb, "NULL::%s", typ)
   106  					}
   107  				}
   108  				if hasArray {
   109  					sb.WriteString(")")
   110  					run(t, sb.String())
   111  				}
   112  			}
   113  		}
   114  	}
   115  }