001package gudusoft.gsqlparser.sqlcmds; 002 003import gudusoft.gsqlparser.EDbVendor; 004import java.util.concurrent.ConcurrentHashMap; 005 006/** 007 * Factory for creating vendor-specific SQL command resolvers. 008 * This factory ensures only the necessary vendor implementations are loaded, 009 * reducing memory footprint and class loading overhead. 010 * 011 * Thread-safe implementation that creates new instances on each request 012 * to avoid shared mutable state between concurrent parser instances. 013 * 014 * @since 3.1.0.9 015 */ 016public class SqlCmdsFactory { 017 018 // Kept for backward compatibility with clearCache() and getCacheSize() methods 019 private static final ConcurrentHashMap<EDbVendor, ISqlCmds> providers = new ConcurrentHashMap<>(); 020 021 /** 022 * Feature flag for gradual migration. When true, uses new modular providers. 023 * When false, falls back to monolithic TSqlCmds (for safety during migration). 024 */ 025 private static boolean useModularProviders = true; 026 027 // Private constructor to prevent instantiation 028 private SqlCmdsFactory() {} 029 030 /** 031 * Gets or creates a vendor-specific SQL command resolver. 032 * Always creates a new instance to ensure thread safety (no shared mutable state). 033 * 034 * @param vendor Database vendor 035 * @return SQL command resolver for the vendor 036 * @throws IllegalArgumentException if vendor is null or unsupported 037 */ 038 public static ISqlCmds get(EDbVendor vendor) { 039 if (vendor == null) { 040 throw new IllegalArgumentException("Database vendor cannot be null"); 041 } 042 043 // Always create new instance - no caching to avoid shared mutable state 044 return createProvider(vendor); 045 } 046 047 /** 048 * Creates a new provider instance for the given vendor. 049 * Called for every get() request to ensure thread safety. 050 */ 051 private static ISqlCmds createProvider(EDbVendor vendor) { 052 if (!useModularProviders) { 053 // Migration safety: use monolithic adapter during transition 054 return new TSqlCmdsAdapter(vendor); 055 } 056 057 // Create vendor-specific provider 058 switch (vendor) { 059 case dbvoracle: 060 return new TSqlCmdsOracle(); 061 case dbvaccess: 062 case dbvmssql: 063 return new TSqlCmdsMssql(); 064 case dbvpostgresql: 065 return new TSqlCmdsPostgresql(); 066 case dbvmysql: 067 return new TSqlCmdsMysql(); 068 case dbvredshift: 069 return new TSqlCmdsRedshift(); 070 case dbvgreenplum: 071 return new TSqlCmdsGreenplum(); 072 case dbvsnowflake: 073 return new TSqlCmdsSnowflake(); 074 case dbvbigquery: 075 return new TSqlCmdsBigquery(); 076 case dbvteradata: 077 return new TSqlCmdsTeradata(); 078 case dbvhive: 079 return new TSqlCmdsHive(); 080 case dbvimpala: 081 return new TSqlCmdsImpala(); 082 case dbvansi: 083 case dbvdb2: 084 return new TSqlCmdsDb2(); 085 case dbvsybase: 086 return new TSqlCmdsSybase(); 087 case dbvsybasease: 088 return new TSqlCmdsSybaseAse(); 089 case dbvsqlanywhere: 090 return new TSqlCmdsSqlAnywhere(); 091 case dbvsybaseiq: 092 return new TSqlCmdsSybaseIq(); 093 case dbvinformix: 094 return new TSqlCmdsInformix(); 095 case dbvhana: 096 return new TSqlCmdsHana(); 097 case dbvvertica: 098 return new TSqlCmdsVertica(); 099 case dbvcouchbase: 100 return new TSqlCmdsCouchbase(); 101 case dbvflink: 102 return new TSqlCmdsFlink(); 103 case dbvsparksql: 104 return new TSqlCmdsSparksql(); 105 case dbvtrino: 106 case dbvpresto: 107 return new TSqlCmdsPresto(); 108 case dbvathena: 109 return new TSqlCmdsAthena(); 110 case dbvdatabricks: 111 return new TSqlCmdsDatabricks(); 112 case dbvdoris: 113 return new TSqlCmdsDoris(); 114 case dbvstarrocks: 115 return new TSqlCmdsStarrocks(); 116 case dbvnetezza: 117 return new TSqlCmdsNetezza(); 118 case dbvmdx: 119 return new TSqlCmdsMdx(); 120 case dbvgaussdb: 121 return new TSqlCmdsGaussdb(); 122 case dbvduckdb: 123 return new TSqlCmdsDuckdb(); 124 case dbvedb: 125 return new TSqlCmdsEdb(); 126 case dbvdameng: 127 return new TSqlCmdsDameng(); 128 case dbvoceanbase: 129 return new TSqlCmdsOceanbase(); 130 case dbvopenedge: 131 return new TSqlCmdsOpenedge(); 132 case dbvsqlite: 133 return new TSqlCmdsSqlite(); 134 case dbvclickhouse: 135 return new TSqlCmdsClickhouse(); 136 case dbvexasol: 137 return new TSqlCmdsExasol(); 138 case dbvsoql: 139 case dbvodbc: // odbc use mssql commands 140 TSqlCmdsMssql mssqlCmds = new TSqlCmdsMssql(); 141 mssqlCmds.setVendor(vendor); 142 return mssqlCmds; // TSqlCmdsOdbc(); 143 default: 144 // For generic or unknown vendors, use a default implementation 145 return new TSqlCmdsMssql(); 146 } 147 } 148 149 /** 150 * Clears the provider cache. Useful for testing and memory management. 151 */ 152 public static void clearCache() { 153 providers.clear(); 154 } 155 156 /** 157 * Sets whether to use modular providers or fall back to monolithic TSqlCmds. 158 * @param useModular true to use new modular system, false for monolithic 159 */ 160 public static void setUseModularProviders(boolean useModular) { 161 useModularProviders = useModular; 162 if (useModular != useModularProviders) { 163 clearCache(); // Clear cache when switching modes 164 } 165 } 166 167 /** 168 * Gets the number of cached providers (for monitoring/debugging). 169 * @return Number of providers currently in cache 170 */ 171 public static int getCacheSize() { 172 return providers.size(); 173 } 174}