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 }