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}