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 dbvclickhouse: 065 case dbvpostgresql: 066 return new TSqlCmdsPostgresql(); 067 case dbvmysql: 068 return new TSqlCmdsMysql(); 069 case dbvredshift: 070 return new TSqlCmdsRedshift(); 071 case dbvgreenplum: 072 return new TSqlCmdsGreenplum(); 073 case dbvsnowflake: 074 return new TSqlCmdsSnowflake(); 075 case dbvbigquery: 076 return new TSqlCmdsBigquery(); 077 case dbvteradata: 078 return new TSqlCmdsTeradata(); 079 case dbvhive: 080 case dbvimpala: // Impala uses Hive commands 081 return new TSqlCmdsHive(); 082 case dbvansi: 083 case dbvdb2: 084 return new TSqlCmdsDb2(); 085 case dbvsybase: 086 return new TSqlCmdsSybase(); 087 case dbvinformix: 088 return new TSqlCmdsInformix(); 089 case dbvhana: 090 return new TSqlCmdsHana(); 091 case dbvvertica: 092 return new TSqlCmdsVertica(); 093 case dbvcouchbase: 094 return new TSqlCmdsCouchbase(); 095 case dbvsparksql: 096 return new TSqlCmdsSparksql(); 097 case dbvtrino: 098 case dbvpresto: 099 return new TSqlCmdsPresto(); 100 case dbvathena: 101 return new TSqlCmdsAthena(); 102 case dbvdatabricks: 103 return new TSqlCmdsDatabricks(); 104 case dbvnetezza: 105 return new TSqlCmdsNetezza(); 106 case dbvmdx: 107 return new TSqlCmdsMdx(); 108 case dbvgaussdb: 109 return new TSqlCmdsGaussdb(); 110 case dbvopenedge: 111 return new TSqlCmdsOpenedge(); 112 case dbvsoql: 113 case dbvodbc: // odbc use mssql commands 114 TSqlCmdsMssql mssqlCmds = new TSqlCmdsMssql(); 115 mssqlCmds.setVendor(vendor); 116 return mssqlCmds; // TSqlCmdsOdbc(); 117 default: 118 // For generic or unknown vendors, use a default implementation 119 return new TSqlCmdsMssql(); 120 } 121 } 122 123 /** 124 * Clears the provider cache. Useful for testing and memory management. 125 */ 126 public static void clearCache() { 127 providers.clear(); 128 } 129 130 /** 131 * Sets whether to use modular providers or fall back to monolithic TSqlCmds. 132 * @param useModular true to use new modular system, false for monolithic 133 */ 134 public static void setUseModularProviders(boolean useModular) { 135 useModularProviders = useModular; 136 if (useModular != useModularProviders) { 137 clearCache(); // Clear cache when switching modes 138 } 139 } 140 141 /** 142 * Gets the number of cached providers (for monitoring/debugging). 143 * @return Number of providers currently in cache 144 */ 145 public static int getCacheSize() { 146 return providers.size(); 147 } 148}