001package gudusoft.gsqlparser.sqlenv; 002 003/** 004 * SQL synonyms object. 005 * 006 * <p>A synonym is an alias for another schema object (its <em>base target</em>). 007 * Besides the synonym name, this class records the base object it points at as a 008 * tri-state (database/catalog, schema, object) triple. Any of the three may be 009 * {@code null} when "unknown": a {@code null} {@link #getSourceDatabase()} / 010 * {@link #getSourceSchema()} means "same database/schema as the synonym itself", 011 * resolved lazily by {@link #resolveBaseTable()}. Cross-database base targets are 012 * allowed (a synonym can point at an object in another database). 013 */ 014public class TSQLSynonyms extends TSQLSchemaObject { 015 016 private String sourceDatabase; 017 private String sourceSchema; 018 private String sourceName; 019 020 public TSQLSynonyms(TSQLSchema sqlSchema, String synonymsName){ 021 super(sqlSchema,synonymsName,ESQLDataObjectType.dotSynonyms); 022 } 023 024 /** 025 * database/catalog of the base object this synonym points at. 026 * {@code null} means "the same database as this synonym". 027 * 028 * @return base database name, or {@code null} when unknown 029 */ 030 public String getSourceDatabase() { 031 return sourceDatabase; 032 } 033 034 public void setSourceDatabase(String sourceDatabase) { 035 this.sourceDatabase = sourceDatabase; 036 } 037 038 /** 039 * schema of the base object this synonym points at. 040 * {@code null} means "the same schema as this synonym". 041 * 042 * @return base schema name, or {@code null} when unknown 043 */ 044 public String getSourceSchema() { 045 return sourceSchema; 046 } 047 048 public void setSourceSchema(String sourceSchema) { 049 this.sourceSchema = sourceSchema; 050 } 051 052 /** 053 * name of the base object this synonym points at. 054 * 055 * @return base object name, or {@code null} when unknown 056 */ 057 public String getSourceName() { 058 return sourceName; 059 } 060 061 public void setSourceName(String sourceName) { 062 this.sourceName = sourceName; 063 } 064 065 /** 066 * Record the base target this synonym points at in one call. 067 * 068 * @param sourceDatabase base database/catalog, or {@code null} for the synonym's own database 069 * @param sourceSchema base schema, or {@code null} for the synonym's own schema 070 * @param sourceName base object name 071 */ 072 public void setBaseTarget(String sourceDatabase, String sourceSchema, String sourceName) { 073 this.sourceDatabase = sourceDatabase; 074 this.sourceSchema = sourceSchema; 075 this.sourceName = sourceName; 076 } 077 078 /** 079 * whether this synonym carries a base target (a non-empty source object name). 080 * 081 * @return true if the base object name is known 082 */ 083 public boolean hasBaseTarget() { 084 return sourceName != null && !sourceName.trim().isEmpty(); 085 } 086 087 /** 088 * the fully qualified name of the base object this synonym points at, in 089 * {@code database.schema.object} form, defaulting the database/schema to the 090 * synonym's own catalog/schema when the source parts are unknown. 091 * 092 * @return qualified base name, or {@code null} when there is no base target 093 */ 094 public String getQualifiedBaseName() { 095 if (!hasBaseTarget()) { 096 return null; 097 } 098 String db = (sourceDatabase != null && !sourceDatabase.trim().isEmpty()) 099 ? sourceDatabase 100 : (schema != null && schema.getCatalog() != null ? schema.getCatalog().getName() : null); 101 String sch = (sourceSchema != null && !sourceSchema.trim().isEmpty()) 102 ? sourceSchema 103 : (schema != null ? schema.getName() : null); 104 StringBuilder builder = new StringBuilder(); 105 builder.append(db == null ? "" : db).append('.') 106 .append(sch == null ? "" : sch).append('.') 107 .append(sourceName); 108 return builder.toString(); 109 } 110 111 /** 112 * Dereference this synonym to its base table/view by resolving the recorded 113 * base target against the owning SQL environment. 114 * 115 * @return the base {@link TSQLTable} (which may itself be a view), or 116 * {@code null} when there is no base target or it cannot be resolved 117 */ 118 public TSQLTable resolveBaseTable() { 119 if (sqlEnv == null || !hasBaseTarget()) { 120 return null; 121 } 122 String qualifiedBaseName = getQualifiedBaseName(); 123 if (qualifiedBaseName == null) { 124 return null; 125 } 126 // Resolve to a table/view only (never re-enter synonym resolution) so a 127 // self/mutually referencing synonym cannot recurse indefinitely. 128 TSQLSchemaObject baseObject = 129 sqlEnv.searchSchemaObject(qualifiedBaseName, ESQLDataObjectType.dotTable); 130 if (baseObject instanceof TSQLTable) { 131 return (TSQLTable) baseObject; 132 } 133 return null; 134 } 135 136 public String getBaseTableQualifiedName() { 137 return getQualifiedBaseName(); 138 } 139 140}