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