Jelajahi Sumber

feat(db): add dialect factory for database dialect handling

Billy Barrow 1 bulan lalu
induk
melakukan
45ed34433d
2 mengubah file dengan 135 tambahan dan 0 penghapusan
  1. 134 0
      src/dialect-factory.vala
  2. 1 0
      src/meson.build

+ 134 - 0
src/dialect-factory.vala

@@ -0,0 +1,134 @@
+using InvercargillSql.Dialects;
+
+namespace InvercargillSql {
+
+    /**
+     * Static factory for creating SQL dialects based on connection schemes.
+     * 
+     * This factory maintains a registry of dialect creators indexed by scheme.
+     * The SQLite dialect is automatically registered on first use.
+     * 
+     * Example usage:
+     * ```vala
+     * // Create dialect from scheme string
+     * var dialect = DialectFactory.create("sqlite");
+     * 
+     * // Create dialect from connection string
+     * var cs = ConnectionString.parse("sqlite:///mydb.sqlite");
+     * var dialect = DialectFactory.create_from_connection_string(cs);
+     * 
+     * // Register custom dialect
+     * DialectFactory.register_dialect("postgresql", () => new PostgresDialect());
+     * var dialect = DialectFactory.create("postgresql");
+     * ```
+     */
+    public class DialectFactory : Object {
+
+        private static bool _sqlite_registered = false;
+        private static SqlDialect? _sqlite_dialect = null;
+
+        /**
+         * Creates a SQL dialect based on a scheme string.
+         * 
+         * The scheme is case-insensitive (e.g., "sqlite" and "SQLite" both work).
+         * 
+         * @param scheme The database scheme (e.g., "sqlite", "postgresql", "mysql")
+         * @return A SqlDialect instance for the specified scheme
+         * @throws SqlError.INVALID_CONNECTION_STRING if no dialect is registered for the scheme
+         */
+        public static SqlDialect create(string scheme) throws SqlError {
+            string scheme_lower = scheme.down();
+
+            if (scheme_lower == "sqlite") {
+                if (!_sqlite_registered) {
+                    _sqlite_dialect = new SqliteDialect();
+                    _sqlite_registered = true;
+                }
+                return _sqlite_dialect;
+            }
+
+            throw new SqlError.INVALID_CONNECTION_STRING(
+                "No SQL dialect registered for scheme: %s".printf(scheme)
+            );
+        }
+
+        /**
+         * Creates a SQL dialect from a ConnectionString object.
+         * 
+         * Extracts the scheme from the connection string and creates
+         * the appropriate dialect.
+         * 
+         * @param connection_string The parsed connection string
+         * @return A SqlDialect instance for the connection string's scheme
+         * @throws SqlError.INVALID_CONNECTION_STRING if no dialect is registered for the scheme
+         */
+        public static SqlDialect create_from_connection_string(ConnectionString connection_string) throws SqlError {
+            return create(connection_string.scheme);
+        }
+
+        /**
+         * Creates a SQL dialect by parsing a connection string.
+         * 
+         * This is a convenience method that parses the connection string
+         * and creates the appropriate dialect in one step.
+         * 
+         * @param connection_string The connection string to parse
+         * @return A SqlDialect instance for the connection string's scheme
+         * @throws SqlError.INVALID_CONNECTION_STRING if parsing fails or no dialect is registered
+         */
+        public static SqlDialect create_from_string(string connection_string) throws SqlError {
+            ConnectionString cs = ConnectionString.parse(connection_string);
+            return create_from_connection_string(cs);
+        }
+
+        /**
+         * Registers a SQL dialect for a scheme.
+         * 
+         * If a dialect is already registered for the scheme, it will be
+         * replaced.
+         * 
+         * Note: Currently only SQLite is supported natively. This method
+         * is provided for future extensibility when additional database
+         * backends are added.
+         * 
+         * @param scheme The scheme (e.g., "sqlite", "postgresql")
+         * @param dialect The SqlDialect instance to register
+         */
+        public static void register_dialect(string scheme, SqlDialect dialect) {
+            string scheme_lower = scheme.down();
+
+            if (scheme_lower == "sqlite") {
+                _sqlite_dialect = dialect;
+                _sqlite_registered = true;
+            }
+            // For other providers, we would extend this with a dictionary
+            // For now, we only support SQLite natively
+        }
+
+        /**
+         * Clears all registered dialects.
+         * 
+         * Useful for testing or when reconfiguring the factory.
+         */
+        public static void clear_dialects() {
+            _sqlite_dialect = null;
+            _sqlite_registered = false;
+        }
+
+        /**
+         * Checks if a dialect is registered for a scheme.
+         * 
+         * @param scheme The scheme to check
+         * @return true if a dialect is registered (or will be auto-created for sqlite)
+         */
+        public static bool has_dialect(string scheme) {
+            string scheme_lower = scheme.down();
+
+            if (scheme_lower == "sqlite") {
+                return true; // SQLite is always available
+            }
+
+            return false;
+        }
+    }
+}

+ 1 - 0
src/meson.build

@@ -20,6 +20,7 @@ sources += files('interfaces/transaction.vala')
 # Connection string factory
 sources += files('connection-string.vala')
 sources += files('connection-factory.vala')
+sources += files('dialect-factory.vala')
 sources += files('providers/connection-provider.vala')
 sources += files('providers/sqlite-provider.vala')