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{}