001package gudusoft.gsqlparser.catalog.runtime; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.catalog.input.CatalogLoadingMode; 005import gudusoft.gsqlparser.catalog.input.model.DefaultsConfig; 006 007import java.util.Collections; 008import java.util.EnumSet; 009import java.util.LinkedHashSet; 010import java.util.Objects; 011import java.util.Set; 012 013/** 014 * Bounded request handed to {@link CatalogProvider#snapshot(CatalogQuery)}. 015 * 016 * <p>Plan ยง7.2. {@code requestedNames} empty means "all" (eager); non-empty restricts to 017 * the explicit set (lazy). Caps from {@code CatalogLoadOptions} are folded in before the 018 * query reaches the provider. {@link #requestedKinds()} empty means "all kinds".</p> 019 */ 020public final class CatalogQuery { 021 022 private final EDbVendor vendor; 023 private final DefaultsConfig defaults; 024 private final CatalogSearchPath searchPath; 025 private final Set<CatalogQualifiedName> requestedNames; 026 private final Set<CatalogObjectKind> requestedKinds; 027 private final boolean includeColumns; 028 private final boolean includeViews; 029 private final boolean includeRoutines; 030 private final CatalogLoadingMode loadingMode; 031 private final long ttlMillis; 032 private final int maxFetchesPerAnalysis; 033 034 private CatalogQuery(Builder b) { 035 if (b.vendor == null) { 036 throw new IllegalArgumentException("CatalogQuery.vendor is required"); 037 } 038 if (b.ttlMillis < 0) { 039 throw new IllegalArgumentException( 040 "CatalogQuery.ttlMillis must be >= 0 (got " + b.ttlMillis + ")"); 041 } 042 if (b.maxFetchesPerAnalysis < 0) { 043 throw new IllegalArgumentException( 044 "CatalogQuery.maxFetchesPerAnalysis must be >= 0 (got " 045 + b.maxFetchesPerAnalysis + ")"); 046 } 047 this.vendor = b.vendor; 048 this.defaults = b.defaults != null ? b.defaults : DefaultsConfig.empty(); 049 this.searchPath = b.searchPath != null ? b.searchPath : CatalogSearchPath.empty(); 050 this.requestedNames = Collections.unmodifiableSet( 051 new LinkedHashSet<CatalogQualifiedName>(b.requestedNames)); 052 this.requestedKinds = b.requestedKinds.isEmpty() 053 ? Collections.<CatalogObjectKind>emptySet() 054 : Collections.unmodifiableSet(EnumSet.copyOf(b.requestedKinds)); 055 this.includeColumns = b.includeColumns; 056 this.includeViews = b.includeViews; 057 this.includeRoutines = b.includeRoutines; 058 this.loadingMode = b.loadingMode != null ? b.loadingMode : CatalogLoadingMode.EAGER; 059 this.ttlMillis = b.ttlMillis; 060 this.maxFetchesPerAnalysis = b.maxFetchesPerAnalysis; 061 } 062 063 public static Builder builder() { 064 return new Builder(); 065 } 066 067 public EDbVendor vendor() { 068 return vendor; 069 } 070 071 public DefaultsConfig defaults() { 072 return defaults; 073 } 074 075 public CatalogSearchPath searchPath() { 076 return searchPath; 077 } 078 079 public Set<CatalogQualifiedName> requestedNames() { 080 return requestedNames; 081 } 082 083 public Set<CatalogObjectKind> requestedKinds() { 084 return requestedKinds; 085 } 086 087 public boolean includeColumns() { 088 return includeColumns; 089 } 090 091 public boolean includeViews() { 092 return includeViews; 093 } 094 095 public boolean includeRoutines() { 096 return includeRoutines; 097 } 098 099 public CatalogLoadingMode loadingMode() { 100 return loadingMode; 101 } 102 103 public long ttlMillis() { 104 return ttlMillis; 105 } 106 107 public int maxFetchesPerAnalysis() { 108 return maxFetchesPerAnalysis; 109 } 110 111 @Override 112 public boolean equals(Object o) { 113 if (this == o) return true; 114 if (!(o instanceof CatalogQuery)) return false; 115 CatalogQuery that = (CatalogQuery) o; 116 return includeColumns == that.includeColumns 117 && includeViews == that.includeViews 118 && includeRoutines == that.includeRoutines 119 && ttlMillis == that.ttlMillis 120 && maxFetchesPerAnalysis == that.maxFetchesPerAnalysis 121 && vendor == that.vendor 122 && defaults.equals(that.defaults) 123 && searchPath.equals(that.searchPath) 124 && requestedNames.equals(that.requestedNames) 125 && requestedKinds.equals(that.requestedKinds) 126 && loadingMode == that.loadingMode; 127 } 128 129 @Override 130 public int hashCode() { 131 return Objects.hash(vendor, defaults, searchPath, requestedNames, requestedKinds, 132 includeColumns, includeViews, includeRoutines, loadingMode, ttlMillis, 133 maxFetchesPerAnalysis); 134 } 135 136 @Override 137 public String toString() { 138 return "CatalogQuery{vendor=" + vendor 139 + ", names=" + requestedNames.size() 140 + ", kinds=" + requestedKinds 141 + ", mode=" + loadingMode + '}'; 142 } 143 144 public static final class Builder { 145 146 private EDbVendor vendor; 147 private DefaultsConfig defaults; 148 private CatalogSearchPath searchPath; 149 private final Set<CatalogQualifiedName> requestedNames = new LinkedHashSet<CatalogQualifiedName>(); 150 private final Set<CatalogObjectKind> requestedKinds = EnumSet.noneOf(CatalogObjectKind.class); 151 private boolean includeColumns = true; 152 private boolean includeViews = true; 153 private boolean includeRoutines = true; 154 private CatalogLoadingMode loadingMode; 155 private long ttlMillis; 156 private int maxFetchesPerAnalysis; 157 158 private Builder() { 159 } 160 161 public Builder vendor(EDbVendor v) { 162 this.vendor = v; 163 return this; 164 } 165 166 public Builder defaults(DefaultsConfig v) { 167 this.defaults = v; 168 return this; 169 } 170 171 public Builder searchPath(CatalogSearchPath v) { 172 this.searchPath = v; 173 return this; 174 } 175 176 public Builder addRequestedName(CatalogQualifiedName v) { 177 if (v == null) { 178 throw new IllegalArgumentException("CatalogQuery requested name may not be null"); 179 } 180 this.requestedNames.add(v); 181 return this; 182 } 183 184 public Builder addRequestedKind(CatalogObjectKind v) { 185 if (v == null) { 186 throw new IllegalArgumentException("CatalogQuery requested kind may not be null"); 187 } 188 this.requestedKinds.add(v); 189 return this; 190 } 191 192 public Builder includeColumns(boolean v) { 193 this.includeColumns = v; 194 return this; 195 } 196 197 public Builder includeViews(boolean v) { 198 this.includeViews = v; 199 return this; 200 } 201 202 public Builder includeRoutines(boolean v) { 203 this.includeRoutines = v; 204 return this; 205 } 206 207 public Builder loadingMode(CatalogLoadingMode v) { 208 this.loadingMode = v; 209 return this; 210 } 211 212 public Builder ttlMillis(long v) { 213 this.ttlMillis = v; 214 return this; 215 } 216 217 public Builder maxFetchesPerAnalysis(int v) { 218 this.maxFetchesPerAnalysis = v; 219 return this; 220 } 221 222 public CatalogQuery build() { 223 return new CatalogQuery(this); 224 } 225 } 226}