Co-authored-by: engchina <atjapan2015@gmail.com>tags/1.0.1
| @@ -1,6 +1,6 @@ | |||
| from typing import Optional | |||
| from pydantic import Field, PositiveInt | |||
| from pydantic import Field | |||
| from pydantic_settings import BaseSettings | |||
| @@ -9,27 +9,38 @@ class OracleConfig(BaseSettings): | |||
| Configuration settings for Oracle database | |||
| """ | |||
| ORACLE_HOST: Optional[str] = Field( | |||
| description="Hostname or IP address of the Oracle database server (e.g., 'localhost' or 'oracle.example.com')", | |||
| ORACLE_USER: Optional[str] = Field( | |||
| description="Username for authenticating with the Oracle database", | |||
| default=None, | |||
| ) | |||
| ORACLE_PORT: PositiveInt = Field( | |||
| description="Port number on which the Oracle database server is listening (default is 1521)", | |||
| default=1521, | |||
| ORACLE_PASSWORD: Optional[str] = Field( | |||
| description="Password for authenticating with the Oracle database", | |||
| default=None, | |||
| ) | |||
| ORACLE_USER: Optional[str] = Field( | |||
| description="Username for authenticating with the Oracle database", | |||
| ORACLE_DSN: Optional[str] = Field( | |||
| description="Oracle database connection string. For traditional database, use format 'host:port/service_name'. " | |||
| "For autonomous database, use the service name from tnsnames.ora in the wallet", | |||
| default=None, | |||
| ) | |||
| ORACLE_PASSWORD: Optional[str] = Field( | |||
| description="Password for authenticating with the Oracle database", | |||
| ORACLE_CONFIG_DIR: Optional[str] = Field( | |||
| description="Directory containing the tnsnames.ora configuration file. Only used in thin mode connection", | |||
| default=None, | |||
| ) | |||
| ORACLE_DATABASE: Optional[str] = Field( | |||
| description="Name of the Oracle database or service to connect to (e.g., 'ORCL' or 'pdborcl')", | |||
| ORACLE_WALLET_LOCATION: Optional[str] = Field( | |||
| description="Oracle wallet directory path containing the wallet files for secure connection", | |||
| default=None, | |||
| ) | |||
| ORACLE_WALLET_PASSWORD: Optional[str] = Field( | |||
| description="Password to decrypt the Oracle wallet, if it is encrypted", | |||
| default=None, | |||
| ) | |||
| ORACLE_IS_AUTONOMOUS: bool = Field( | |||
| description="Flag indicating whether connecting to Oracle Autonomous Database", | |||
| default=False, | |||
| ) | |||
| @@ -23,25 +23,30 @@ oracledb.defaults.fetch_lobs = False | |||
| class OracleVectorConfig(BaseModel): | |||
| host: str | |||
| port: int | |||
| user: str | |||
| password: str | |||
| database: str | |||
| dsn: str | |||
| config_dir: str | None = None | |||
| wallet_location: str | None = None | |||
| wallet_password: str | None = None | |||
| is_autonomous: bool = False | |||
| @model_validator(mode="before") | |||
| @classmethod | |||
| def validate_config(cls, values: dict) -> dict: | |||
| if not values["host"]: | |||
| raise ValueError("config ORACLE_HOST is required") | |||
| if not values["port"]: | |||
| raise ValueError("config ORACLE_PORT is required") | |||
| if not values["user"]: | |||
| raise ValueError("config ORACLE_USER is required") | |||
| if not values["password"]: | |||
| raise ValueError("config ORACLE_PASSWORD is required") | |||
| if not values["database"]: | |||
| raise ValueError("config ORACLE_DB is required") | |||
| if not values["dsn"]: | |||
| raise ValueError("config ORACLE_DSN is required") | |||
| if values.get("is_autonomous", False): | |||
| if not values.get("config_dir"): | |||
| raise ValueError("config_dir is required for autonomous database") | |||
| if not values.get("wallet_location"): | |||
| raise ValueError("wallet_location is required for autonomous database") | |||
| if not values.get("wallet_password"): | |||
| raise ValueError("wallet_password is required for autonomous database") | |||
| return values | |||
| @@ -56,7 +61,7 @@ CREATE TABLE IF NOT EXISTS {table_name} ( | |||
| SQL_CREATE_INDEX = """ | |||
| CREATE INDEX IF NOT EXISTS idx_docs_{table_name} ON {table_name}(text) | |||
| INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS | |||
| ('FILTER CTXSYS.NULL_FILTER SECTION GROUP CTXSYS.HTML_SECTION_GROUP LEXER sys.my_chinese_vgram_lexer') | |||
| ('FILTER CTXSYS.NULL_FILTER SECTION GROUP CTXSYS.HTML_SECTION_GROUP LEXER multilingual_lexer') | |||
| """ | |||
| @@ -103,14 +108,25 @@ class OracleVector(BaseVector): | |||
| ) | |||
| def _create_connection_pool(self, config: OracleVectorConfig): | |||
| return oracledb.create_pool( | |||
| user=config.user, | |||
| password=config.password, | |||
| dsn="{}:{}/{}".format(config.host, config.port, config.database), | |||
| min=1, | |||
| max=50, | |||
| increment=1, | |||
| ) | |||
| pool_params = { | |||
| "user": config.user, | |||
| "password": config.password, | |||
| "dsn": config.dsn, | |||
| "min": 1, | |||
| "max": 50, | |||
| "increment": 1, | |||
| } | |||
| if config.is_autonomous: | |||
| pool_params.update( | |||
| { | |||
| "config_dir": config.config_dir, | |||
| "wallet_location": config.wallet_location, | |||
| "wallet_password": config.wallet_password, | |||
| } | |||
| ) | |||
| return oracledb.create_pool(**pool_params) | |||
| @contextmanager | |||
| def _get_cursor(self): | |||
| @@ -287,10 +303,12 @@ class OracleVectorFactory(AbstractVectorFactory): | |||
| return OracleVector( | |||
| collection_name=collection_name, | |||
| config=OracleVectorConfig( | |||
| host=dify_config.ORACLE_HOST or "localhost", | |||
| port=dify_config.ORACLE_PORT, | |||
| user=dify_config.ORACLE_USER or "system", | |||
| password=dify_config.ORACLE_PASSWORD or "oracle", | |||
| database=dify_config.ORACLE_DATABASE or "orcl", | |||
| dsn=dify_config.ORACLE_DSN or "oracle:1521/freepdb1", | |||
| config_dir=dify_config.ORACLE_CONFIG_DIR, | |||
| wallet_location=dify_config.ORACLE_WALLET_LOCATION, | |||
| wallet_password=dify_config.ORACLE_WALLET_PASSWORD, | |||
| is_autonomous=dify_config.ORACLE_IS_AUTONOMOUS, | |||
| ), | |||
| ) | |||
| @@ -13,11 +13,9 @@ class OracleVectorTest(AbstractVectorTest): | |||
| self.vector = OracleVector( | |||
| collection_name=self.collection_name, | |||
| config=OracleVectorConfig( | |||
| host="localhost", | |||
| port=1521, | |||
| user="dify", | |||
| password="dify", | |||
| database="FREEPDB1", | |||
| dsn="localhost:1521/FREEPDB1", | |||
| ), | |||
| ) | |||
| @@ -483,11 +483,13 @@ CHROMA_AUTH_PROVIDER=chromadb.auth.token_authn.TokenAuthClientProvider | |||
| CHROMA_AUTH_CREDENTIALS= | |||
| # Oracle configuration, only available when VECTOR_STORE is `oracle` | |||
| ORACLE_HOST=oracle | |||
| ORACLE_PORT=1521 | |||
| ORACLE_USER=dify | |||
| ORACLE_PASSWORD=dify | |||
| ORACLE_DATABASE=FREEPDB1 | |||
| ORACLE_DSN=oracle:1521/FREEPDB1 | |||
| ORACLE_CONFIG_DIR=/app/api/storage/wallet | |||
| ORACLE_WALLET_LOCATION=/app/api/storage/wallet | |||
| ORACLE_WALLET_PASSWORD=dify | |||
| ORACLE_IS_AUTONOMOUS=false | |||
| # relyt configurations, only available when VECTOR_STORE is `relyt` | |||
| RELYT_HOST=db | |||
| @@ -197,11 +197,13 @@ x-shared-env: &shared-api-worker-env | |||
| CHROMA_DATABASE: ${CHROMA_DATABASE:-default_database} | |||
| CHROMA_AUTH_PROVIDER: ${CHROMA_AUTH_PROVIDER:-chromadb.auth.token_authn.TokenAuthClientProvider} | |||
| CHROMA_AUTH_CREDENTIALS: ${CHROMA_AUTH_CREDENTIALS:-} | |||
| ORACLE_HOST: ${ORACLE_HOST:-oracle} | |||
| ORACLE_PORT: ${ORACLE_PORT:-1521} | |||
| ORACLE_USER: ${ORACLE_USER:-dify} | |||
| ORACLE_PASSWORD: ${ORACLE_PASSWORD:-dify} | |||
| ORACLE_DATABASE: ${ORACLE_DATABASE:-FREEPDB1} | |||
| ORACLE_DSN: ${ORACLE_DSN:-oracle:1521/FREEPDB1} | |||
| ORACLE_CONFIG_DIR: ${ORACLE_CONFIG_DIR:-/app/api/storage/wallet} | |||
| ORACLE_WALLET_LOCATION: ${ORACLE_WALLET_LOCATION:-/app/api/storage/wallet} | |||
| ORACLE_WALLET_PASSWORD: ${ORACLE_WALLET_PASSWORD:-dify} | |||
| ORACLE_IS_AUTONOMOUS: ${ORACLE_IS_AUTONOMOUS:-false} | |||
| RELYT_HOST: ${RELYT_HOST:-db} | |||
| RELYT_PORT: ${RELYT_PORT:-5432} | |||
| RELYT_USER: ${RELYT_USER:-postgres} | |||
| @@ -5,6 +5,6 @@ create user dify identified by dify DEFAULT TABLESPACE users quota unlimited on | |||
| grant DB_DEVELOPER_ROLE to dify; | |||
| BEGIN | |||
| CTX_DDL.CREATE_PREFERENCE('my_chinese_vgram_lexer','CHINESE_VGRAM_LEXER'); | |||
| CTX_DDL.CREATE_PREFERENCE('dify.multilingual_lexer','CHINESE_VGRAM_LEXER'); | |||
| END; | |||
| / | |||