github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sem/tree/name_part_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 tree_test
    12  
    13  import (
    14  	"testing"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/parser"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    18  	"github.com/cockroachdb/cockroach/pkg/testutils"
    19  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    20  )
    21  
    22  func TestUnresolvedObjectName(t *testing.T) {
    23  	defer leaktest.AfterTest(t)()
    24  	testCases := []struct {
    25  		in, out  string
    26  		expanded string
    27  		err      string
    28  	}{
    29  		{`a`, `a`, `""."".a`, ``},
    30  		{`a.b`, `a.b`, `"".a.b`, ``},
    31  		{`a.b.c`, `a.b.c`, `a.b.c`, ``},
    32  		{`a.b.c.d`, ``, ``, `at or near "\.": syntax error`},
    33  		{`a.""`, ``, ``, `invalid table name: a\.""`},
    34  		{`a.b.""`, ``, ``, `invalid table name: a\.b\.""`},
    35  		{`a.b.c.""`, ``, ``, `at or near "\.": syntax error`},
    36  		{`a."".c`, ``, ``, `invalid table name: a\.""\.c`},
    37  
    38  		// CockroachDB extension: empty catalog name.
    39  		{`"".b.c`, `"".b.c`, `"".b.c`, ``},
    40  
    41  		// Check keywords: disallowed in first position, ok afterwards.
    42  		{`user.x.y`, ``, ``, `syntax error`},
    43  		{`"user".x.y`, `"user".x.y`, `"user".x.y`, ``},
    44  		{`x.user.y`, `x."user".y`, `x."user".y`, ``},
    45  		{`x.user`, `x."user"`, `"".x."user"`, ``},
    46  
    47  		{`foo@bar`, ``, ``, `at or near "@": syntax error`},
    48  		{`test.*`, ``, ``, `at or near "\*": syntax error`},
    49  	}
    50  
    51  	for _, tc := range testCases {
    52  		t.Run(tc.in, func(t *testing.T) {
    53  			name, err := parser.ParseTableName(tc.in)
    54  			if !testutils.IsError(err, tc.err) {
    55  				t.Fatalf("%s: expected %s, but found %v", tc.in, tc.err, err)
    56  			}
    57  			if tc.err != "" {
    58  				return
    59  			}
    60  			tn := name.ToTableName()
    61  			if out := tn.String(); tc.out != out {
    62  				t.Fatalf("%s: expected %s, but found %s", tc.in, tc.out, out)
    63  			}
    64  			tn.ExplicitSchema = true
    65  			tn.ExplicitCatalog = true
    66  			if out := tn.String(); tc.expanded != out {
    67  				t.Fatalf("%s: expected full %s, but found %s", tc.in, tc.expanded, out)
    68  			}
    69  		})
    70  	}
    71  }
    72  
    73  // TestUnresolvedNameAnnotation verifies that we use the annotation
    74  // to produce a fully qualified name when required.
    75  func TestUnresolvedNameAnnotation(t *testing.T) {
    76  	defer leaktest.AfterTest(t)()
    77  	aIdx := tree.AnnotationIdx(1)
    78  	u, err := tree.NewUnresolvedObjectName(1, [3]string{"t"}, aIdx)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	ann := tree.MakeAnnotations(aIdx)
    83  
    84  	expect := func(expected string) {
    85  		t.Helper()
    86  		ctx := tree.NewFmtCtxEx(tree.FmtAlwaysQualifyTableNames, &ann)
    87  		ctx.FormatNode(u)
    88  		if actual := ctx.CloseAndGetString(); actual != expected {
    89  			t.Errorf("expected: `%s`, got `%s`", expected, actual)
    90  		}
    91  	}
    92  
    93  	// No annotation set.
    94  	expect("t")
    95  
    96  	name, err := parser.ParseTableName("db.public.t")
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  	tn := name.ToTableName()
   101  	u.SetAnnotation(&ann, &tn)
   102  
   103  	expect("db.public.t")
   104  
   105  	// No annotation.
   106  	u.AnnIdx = 0
   107  	expect("t")
   108  }