github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/object_name.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/cockroachdb-parser/pkg/sql/sem/catconstants"
    14  
    15  // ObjectName is a common interface for qualified object names.
    16  type ObjectName interface {
    17  	NodeFormatter
    18  	Object() string
    19  	Schema() string
    20  	Catalog() string
    21  	FQString() string
    22  	objectName()
    23  }
    24  
    25  var _ ObjectName = &TableName{}
    26  var _ ObjectName = &TypeName{}
    27  var _ ObjectName = &RoutineName{}
    28  var _ ObjectName = &UnspecifiedObjectName{}
    29  
    30  // objName is the internal type for a qualified object.
    31  type objName struct {
    32  	// ObjectName is the unqualified name for the object
    33  	// (table/view/sequence/function/type).
    34  	ObjectName Name
    35  
    36  	// ObjectNamePrefix is the path to the object.  This can be modified
    37  	// further by name resolution, see name_resolution.go.
    38  	ObjectNamePrefix
    39  }
    40  
    41  func makeQualifiedObjName(db, schema, object Name) objName {
    42  	return makeObjNameWithPrefix(ObjectNamePrefix{
    43  		CatalogName:     db,
    44  		SchemaName:      schema,
    45  		ExplicitSchema:  true,
    46  		ExplicitCatalog: true,
    47  	}, object)
    48  }
    49  
    50  func makeObjNameWithPrefix(prefix ObjectNamePrefix, object Name) objName {
    51  	return objName{
    52  		ObjectName:       object,
    53  		ObjectNamePrefix: prefix,
    54  	}
    55  }
    56  
    57  func (o *objName) Object() string {
    58  	return string(o.ObjectName)
    59  }
    60  
    61  // ToUnresolvedObjectName converts the type name to an unresolved object name.
    62  // Schema and catalog are included if indicated by the ExplicitSchema and
    63  // ExplicitCatalog flags.
    64  func (o *objName) ToUnresolvedObjectName() *UnresolvedObjectName {
    65  	u := &UnresolvedObjectName{}
    66  
    67  	u.NumParts = 1
    68  	u.Parts[0] = string(o.ObjectName)
    69  	if o.ExplicitSchema {
    70  		u.Parts[u.NumParts] = string(o.SchemaName)
    71  		u.NumParts++
    72  	}
    73  	if o.ExplicitCatalog {
    74  		u.Parts[u.NumParts] = string(o.CatalogName)
    75  		u.NumParts++
    76  	}
    77  	return u
    78  }
    79  
    80  func (o *objName) String() string { return AsString(o) }
    81  
    82  // FQString renders the table name in full, not omitting the prefix
    83  // schema and catalog names. Suitable for logging, etc.
    84  func (o *objName) FQString() string {
    85  	ctx := NewFmtCtx(FmtSimple)
    86  	schemaName := o.SchemaName.String()
    87  	// The pg_catalog and pg_extension schemas cannot be referenced from inside
    88  	// an anonymous ("") database. This makes their FQ string always relative.
    89  	if schemaName != catconstants.PgCatalogName && schemaName != catconstants.PgExtensionSchemaName {
    90  		ctx.FormatNode(&o.CatalogName)
    91  		ctx.WriteByte('.')
    92  	}
    93  	ctx.FormatNode(&o.SchemaName)
    94  	ctx.WriteByte('.')
    95  	ctx.FormatNode(&o.ObjectName)
    96  	return ctx.CloseAndGetString()
    97  }
    98  
    99  // Format implements the NodeFormatter interface.
   100  func (o *objName) Format(ctx *FmtCtx) {
   101  	ctx.FormatNode(&o.ObjectNamePrefix)
   102  	if o.ExplicitSchema || ctx.alwaysFormatTablePrefix() {
   103  		ctx.WriteByte('.')
   104  	}
   105  	ctx.FormatNode(&o.ObjectName)
   106  }
   107  
   108  // UnspecifiedObjectName is an object name correspond to any object type.
   109  type UnspecifiedObjectName struct {
   110  	objName
   111  }
   112  
   113  func (u UnspecifiedObjectName) objectName() {}
   114  
   115  // ObjectNamePrefix corresponds to the path prefix of an object name.
   116  type ObjectNamePrefix struct {
   117  	CatalogName Name
   118  	SchemaName  Name
   119  
   120  	// ExplicitCatalog is true iff the catalog was explicitly specified
   121  	// or it needs to be rendered during pretty-printing.
   122  	ExplicitCatalog bool
   123  	// ExplicitSchema is true iff the schema was explicitly specified
   124  	// or it needs to be rendered during pretty-printing.
   125  	ExplicitSchema bool
   126  }
   127  
   128  // Format implements the NodeFormatter interface.
   129  func (tp *ObjectNamePrefix) Format(ctx *FmtCtx) {
   130  	alwaysFormat := ctx.alwaysFormatTablePrefix()
   131  	if tp.ExplicitSchema || alwaysFormat {
   132  		if tp.ExplicitCatalog || alwaysFormat {
   133  			ctx.FormatNode(&tp.CatalogName)
   134  			ctx.WriteByte('.')
   135  		}
   136  		ctx.FormatNode(&tp.SchemaName)
   137  	}
   138  }
   139  
   140  func (tp *ObjectNamePrefix) String() string { return AsString(tp) }
   141  
   142  // Schema retrieves the unqualified schema name.
   143  func (tp *ObjectNamePrefix) Schema() string {
   144  	return string(tp.SchemaName)
   145  }
   146  
   147  // Catalog retrieves the unqualified catalog name.
   148  func (tp *ObjectNamePrefix) Catalog() string {
   149  	return string(tp.CatalogName)
   150  }
   151  
   152  // ObjectNamePrefixList is a list of ObjectNamePrefix
   153  type ObjectNamePrefixList []ObjectNamePrefix
   154  
   155  // Format implements the NodeFormatter interface.
   156  func (tp ObjectNamePrefixList) Format(ctx *FmtCtx) {
   157  	for idx, objectNamePrefix := range tp {
   158  		ctx.FormatNode(&objectNamePrefix)
   159  		if idx != len(tp)-1 {
   160  			ctx.WriteString(", ")
   161  		}
   162  	}
   163  }
   164  
   165  // UnresolvedObjectName is an unresolved qualified name for a database object
   166  // (table, view, etc). It is like UnresolvedName but more restrictive.
   167  // It should only be constructed via NewUnresolvedObjectName.
   168  type UnresolvedObjectName struct {
   169  	// NumParts indicates the number of name parts specified; always 1 or greater.
   170  	NumParts int
   171  
   172  	// Parts are the name components, in reverse order.
   173  	// There are at most 3: object name, schema, catalog/db.
   174  	//
   175  	// Note: Parts has a fixed size so that we avoid a heap allocation for the
   176  	// slice every time we construct an UnresolvedObjectName. It does imply
   177  	// however that Parts does not have a meaningful "length"; its actual length
   178  	// (the number of parts specified) is populated in NumParts above.
   179  	Parts [3]string
   180  
   181  	// UnresolvedObjectName can be annotated with a *tree.TableName.
   182  	AnnotatedNode
   183  }
   184  
   185  // UnresolvedObjectName implements TableExpr.
   186  func (*UnresolvedObjectName) tableExpr() {}
   187  
   188  // NewUnresolvedObjectName creates an unresolved object name, verifying that it
   189  // is well-formed.
   190  func NewUnresolvedObjectName(
   191  	numParts int, parts [3]string, annotationIdx AnnotationIdx,
   192  ) (*UnresolvedObjectName, error) {
   193  	n, err := MakeUnresolvedObjectName(numParts, parts, annotationIdx)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  	return &n, nil
   198  }
   199  
   200  // MakeUnresolvedObjectName creates an unresolved object name, verifying that it
   201  // is well-formed.
   202  func MakeUnresolvedObjectName(
   203  	numParts int, parts [3]string, annotationIdx AnnotationIdx,
   204  ) (UnresolvedObjectName, error) {
   205  	u := UnresolvedObjectName{
   206  		NumParts:      numParts,
   207  		Parts:         parts,
   208  		AnnotatedNode: AnnotatedNode{AnnIdx: annotationIdx},
   209  	}
   210  	if u.NumParts < 1 {
   211  		forErr := u // prevents u from escaping
   212  		return UnresolvedObjectName{}, newInvTableNameError(&forErr)
   213  	}
   214  
   215  	// Check that all the parts specified are not empty.
   216  	// It's OK if the catalog name is empty.
   217  	// We allow this in e.g. `select * from "".crdb_internal.tables`.
   218  	lastCheck := u.NumParts
   219  	if lastCheck > 2 {
   220  		lastCheck = 2
   221  	}
   222  	for i := 0; i < lastCheck; i++ {
   223  		if len(u.Parts[i]) == 0 {
   224  			forErr := u // prevents u from escaping
   225  			return UnresolvedObjectName{}, newInvTableNameError(&forErr)
   226  		}
   227  	}
   228  	return u, nil
   229  }
   230  
   231  // Resolved returns the resolved name in the annotation for this node (or nil if
   232  // there isn't one).
   233  func (u *UnresolvedObjectName) Resolved(ann *Annotations) ObjectName {
   234  	r := u.GetAnnotation(ann)
   235  	if r == nil {
   236  		return nil
   237  	}
   238  	return r.(ObjectName)
   239  }
   240  
   241  // Format implements the NodeFormatter interface.
   242  func (u *UnresolvedObjectName) Format(ctx *FmtCtx) {
   243  	// If we want to format the corresponding resolved name, look it up in the
   244  	// annotation.
   245  	if ctx.HasFlags(FmtAlwaysQualifyTableNames) || ctx.tableNameFormatter != nil {
   246  		if ctx.tableNameFormatter != nil && ctx.ann == nil {
   247  			// TODO(radu): this is a temporary hack while we transition to using
   248  			// unresolved names everywhere. We will need to revisit and see if we need
   249  			// to switch to (or add) an UnresolvedObjectName formatter.
   250  			tn := u.ToTableName()
   251  			tn.Format(ctx)
   252  			return
   253  		}
   254  
   255  		if n := u.Resolved(ctx.ann); n != nil {
   256  			n.Format(ctx)
   257  			return
   258  		}
   259  	}
   260  
   261  	for i := u.NumParts; i > 0; i-- {
   262  		// The first part to print is the last item in u.Parts. It is also
   263  		// a potentially restricted name to disambiguate from keywords in
   264  		// the grammar, so print it out as a "Name". Every part after that is
   265  		// necessarily an unrestricted name.
   266  		if i == u.NumParts {
   267  			ctx.FormatNode((*Name)(&u.Parts[i-1]))
   268  		} else {
   269  			ctx.WriteByte('.')
   270  			ctx.FormatNode((*UnrestrictedName)(&u.Parts[i-1]))
   271  		}
   272  	}
   273  }
   274  
   275  func (u *UnresolvedObjectName) String() string { return AsString(u) }
   276  
   277  // TODO(radu): the schema and catalog names might not be in the right places; we
   278  // would only figure that out during name resolution. This method is temporary,
   279  // while we change all the code paths to only use TableName after resolution.
   280  func (u *UnresolvedObjectName) toObjName() objName {
   281  	return objName{
   282  		ObjectName: Name(u.Parts[0]),
   283  		ObjectNamePrefix: ObjectNamePrefix{
   284  			SchemaName:      Name(u.Parts[1]),
   285  			CatalogName:     Name(u.Parts[2]),
   286  			ExplicitSchema:  u.NumParts >= 2,
   287  			ExplicitCatalog: u.NumParts >= 3,
   288  		},
   289  	}
   290  }
   291  
   292  // ToTableName converts the unresolved name to a table name.
   293  func (u *UnresolvedObjectName) ToTableName() TableName {
   294  	return TableName{u.toObjName()}
   295  }
   296  
   297  // ToRoutineName converts the unresolved name to a function name.
   298  func (u *UnresolvedObjectName) ToRoutineName() RoutineName {
   299  	return RoutineName{u.toObjName()}
   300  }
   301  
   302  // ToUnresolvedName converts the unresolved object name to the more general
   303  // unresolved name.
   304  func (u *UnresolvedObjectName) ToUnresolvedName() *UnresolvedName {
   305  	return &UnresolvedName{
   306  		NumParts: u.NumParts,
   307  		Parts:    NameParts{u.Parts[0], u.Parts[1], u.Parts[2]},
   308  	}
   309  }
   310  
   311  // Utility methods below for operating on UnresolvedObjectName more natural.
   312  
   313  // Object returns the unqualified object name.
   314  func (u *UnresolvedObjectName) Object() string {
   315  	return u.Parts[0]
   316  }
   317  
   318  // Schema returns the schema of the object.
   319  func (u *UnresolvedObjectName) Schema() string {
   320  	return u.Parts[1]
   321  }
   322  
   323  // Catalog returns the catalog of the object.
   324  func (u *UnresolvedObjectName) Catalog() string {
   325  	return u.Parts[2]
   326  }
   327  
   328  // HasExplicitSchema returns whether a schema is specified on the object.
   329  func (u *UnresolvedObjectName) HasExplicitSchema() bool {
   330  	return u.NumParts >= 2
   331  }
   332  
   333  // HasExplicitCatalog returns whether a catalog is specified on the object.
   334  func (u *UnresolvedObjectName) HasExplicitCatalog() bool {
   335  	return u.NumParts >= 3
   336  }
   337  
   338  // UnresolvedRoutineName is an unresolved function or procedure name. The two
   339  // implementations of this interface are used to differentiate between the two
   340  // types of routines for things like error messages.
   341  type UnresolvedRoutineName interface {
   342  	UnresolvedName() *UnresolvedName
   343  	isUnresolvedRoutineName()
   344  }
   345  
   346  // UnresolvedFunctionName is an unresolved function name.
   347  type UnresolvedFunctionName struct {
   348  	u *UnresolvedName
   349  }
   350  
   351  // MakeUnresolvedFunctionName returns a new UnresolvedFunctionName containing
   352  // the give UnresolvedName.
   353  func MakeUnresolvedFunctionName(u *UnresolvedName) UnresolvedFunctionName {
   354  	return UnresolvedFunctionName{u: u}
   355  }
   356  
   357  // UnresolvedName implements the UnresolvedRoutineName interface.
   358  func (u UnresolvedFunctionName) UnresolvedName() *UnresolvedName {
   359  	return u.u
   360  }
   361  
   362  // isUnresolvedRoutineName implements the UnresolvedRoutineName interface.
   363  func (u UnresolvedFunctionName) isUnresolvedRoutineName() {}
   364  
   365  var _ UnresolvedRoutineName = UnresolvedFunctionName{}
   366  
   367  // UnresolvedProcedureName is an unresolved procedure name.
   368  type UnresolvedProcedureName struct {
   369  	u *UnresolvedName
   370  }
   371  
   372  // MakeUnresolvedProcedureName returns a new UnresolvedProcedureName containing
   373  // the give UnresolvedName.
   374  func MakeUnresolvedProcedureName(u *UnresolvedName) UnresolvedProcedureName {
   375  	return UnresolvedProcedureName{u: u}
   376  }
   377  
   378  // isUnresolvedRoutineName implements the UnresolvedRoutineName interface.
   379  func (u UnresolvedProcedureName) isUnresolvedRoutineName() {}
   380  
   381  // UnresolvedName implements the UnresolvedRoutineName interface.
   382  func (u UnresolvedProcedureName) UnresolvedName() *UnresolvedName {
   383  	return u.u
   384  }
   385  
   386  var _ UnresolvedRoutineName = UnresolvedProcedureName{}