001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to you under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package gudusoft.gsqlparser.sqlenv.calcite; 018 019import gudusoft.gsqlparser.EDbVendor; 020import gudusoft.gsqlparser.ext.calcite.sqlnamematcher.SqlNameMatcher; 021import gudusoft.gsqlparser.ext.calcite.sqlnamematcher.SqlNameMatchers; 022import gudusoft.gsqlparser.sqlenv.ESQLDataObjectType; 023import gudusoft.gsqlparser.sqlenv.TSQLEnv; 024 025import java.util.EnumMap; 026import java.util.Map; 027 028/** 029 * Factory for creating SqlNameMatcher instances per database vendor and object type. 030 * 031 * <p>This class bridges GSP's existing case sensitivity configuration (stored in 032 * TSQLEnv's EnumMaps) to Apache Calcite's SqlNameMatcher framework.</p> 033 * 034 * <p>Design rationale: Instead of duplicating vendor-specific case rules, this factory 035 * reads from TSQLEnv's existing static maps and creates appropriate matchers on demand.</p> 036 * 037 * @since 3.2.0.3 (Phase 1) 038 */ 039public class NamePolicyFactory { 040 041 private final EDbVendor vendor; 042 043 // Cache matchers per type to avoid repeated creation 044 private final Map<ESQLDataObjectType, SqlNameMatcher> matcherCache = 045 new EnumMap<>(ESQLDataObjectType.class); 046 047 /** 048 * Creates a new NamePolicyFactory for the specified database vendor. 049 * 050 * @param vendor the database vendor 051 */ 052 public NamePolicyFactory(EDbVendor vendor) { 053 if (vendor == null) { 054 throw new IllegalArgumentException("vendor cannot be null"); 055 } 056 this.vendor = vendor; 057 } 058 059 /** 060 * Returns the database vendor associated with this factory. 061 * 062 * @return the database vendor 063 */ 064 public EDbVendor getVendor() { 065 return vendor; 066 } 067 068 /** 069 * Gets or creates a SqlNameMatcher for the specified object type. 070 * 071 * <p>The matcher's case sensitivity is determined by querying TSQLEnv's 072 * static maps (columnCollationCaseSensitive, tableCollationCaseSensitive, etc.)</p> 073 * 074 * <p>Results are cached to avoid repeated map lookups.</p> 075 * 076 * @param type the SQL data object type (table, column, function, etc.) 077 * @return a SqlNameMatcher configured for the vendor/type combination 078 */ 079 public SqlNameMatcher getMatcherForType(ESQLDataObjectType type) { 080 // Check cache first 081 SqlNameMatcher cached = matcherCache.get(type); 082 if (cached != null) { 083 return cached; 084 } 085 086 // Create new matcher based on TSQLEnv's existing configuration 087 SqlNameMatcher matcher = createMatcher(type); 088 matcherCache.put(type, matcher); 089 return matcher; 090 } 091 092 /** 093 * Creates a SqlNameMatcher by reading TSQLEnv's case sensitivity maps. 094 * 095 * @param type the object type 096 * @return a newly created SqlNameMatcher 097 */ 098 private SqlNameMatcher createMatcher(ESQLDataObjectType type) { 099 boolean caseSensitive; 100 101 switch (type) { 102 case dotCatalog: 103 case dotSchema: 104 // Catalog and schema use the catalogCollationCaseSensitive map 105 caseSensitive = TSQLEnv.catalogCollationCaseSensitive.get(vendor); 106 break; 107 108 case dotTable: 109 case dotProcedure: 110 case dotTrigger: 111 case dotOraclePackage: 112 // Tables, procedures, triggers, and Oracle packages use tableCollationCaseSensitive 113 caseSensitive = TSQLEnv.tableCollationCaseSensitive.get(vendor); 114 break; 115 116 case dotFunction: 117 // Functions have their own map 118 caseSensitive = TSQLEnv.functionCollationCaseSensitive.get(vendor); 119 break; 120 121 case dotColumn: 122 // Columns have their own map 123 caseSensitive = TSQLEnv.columnCollationCaseSensitive.get(vendor); 124 break; 125 126 default: 127 // Everything else uses the default map 128 caseSensitive = TSQLEnv.defaultCollationCaseSensitive.get(vendor); 129 break; 130 } 131 132 // Create a Calcite matcher with the appropriate case sensitivity 133 return SqlNameMatchers.withCaseSensitive(caseSensitive); 134 } 135 136 /** 137 * Convenience method to check if a specific object type is case-sensitive 138 * for this vendor. 139 * 140 * @param type the object type 141 * @return true if case-sensitive, false otherwise 142 */ 143 public boolean isCaseSensitive(ESQLDataObjectType type) { 144 return getMatcherForType(type).isCaseSensitive(); 145 } 146}