databao-context-engine 0.1.1__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- databao_context_engine/__init__.py +32 -7
- databao_context_engine/build_sources/__init__.py +4 -0
- databao_context_engine/build_sources/{internal/build_runner.py → build_runner.py} +31 -27
- databao_context_engine/build_sources/build_service.py +53 -0
- databao_context_engine/build_sources/build_wiring.py +82 -0
- databao_context_engine/build_sources/export_results.py +41 -0
- databao_context_engine/build_sources/{internal/plugin_execution.py → plugin_execution.py} +11 -18
- databao_context_engine/cli/add_datasource_config.py +49 -44
- databao_context_engine/cli/commands.py +40 -55
- databao_context_engine/cli/info.py +3 -2
- databao_context_engine/databao_context_engine.py +127 -0
- databao_context_engine/databao_context_project_manager.py +147 -30
- databao_context_engine/{datasource_config → datasources}/check_config.py +31 -23
- databao_context_engine/datasources/datasource_context.py +90 -0
- databao_context_engine/datasources/datasource_discovery.py +143 -0
- databao_context_engine/datasources/types.py +194 -0
- databao_context_engine/generate_configs_schemas.py +4 -5
- databao_context_engine/init_project.py +25 -3
- databao_context_engine/introspection/property_extract.py +76 -57
- databao_context_engine/llm/__init__.py +10 -0
- databao_context_engine/llm/api.py +57 -0
- databao_context_engine/llm/descriptions/ollama.py +1 -3
- databao_context_engine/llm/errors.py +2 -8
- databao_context_engine/llm/factory.py +5 -2
- databao_context_engine/llm/install.py +26 -30
- databao_context_engine/llm/runtime.py +3 -5
- databao_context_engine/llm/service.py +1 -3
- databao_context_engine/mcp/mcp_runner.py +4 -2
- databao_context_engine/mcp/mcp_server.py +9 -11
- databao_context_engine/plugin_loader.py +110 -0
- databao_context_engine/pluginlib/build_plugin.py +12 -29
- databao_context_engine/pluginlib/config.py +16 -2
- databao_context_engine/plugins/{athena_db_plugin.py → databases/athena/athena_db_plugin.py} +3 -3
- databao_context_engine/plugins/databases/athena/athena_introspector.py +161 -0
- databao_context_engine/plugins/{base_db_plugin.py → databases/base_db_plugin.py} +6 -5
- databao_context_engine/plugins/databases/base_introspector.py +11 -12
- databao_context_engine/plugins/{clickhouse_db_plugin.py → databases/clickhouse/clickhouse_db_plugin.py} +3 -3
- databao_context_engine/plugins/databases/{clickhouse_introspector.py → clickhouse/clickhouse_introspector.py} +24 -16
- databao_context_engine/plugins/databases/duckdb/duckdb_db_plugin.py +12 -0
- databao_context_engine/plugins/databases/{duckdb_introspector.py → duckdb/duckdb_introspector.py} +7 -12
- databao_context_engine/plugins/databases/introspection_model_builder.py +1 -1
- databao_context_engine/plugins/databases/introspection_scope.py +11 -9
- databao_context_engine/plugins/databases/introspection_scope_matcher.py +2 -5
- databao_context_engine/plugins/{mssql_db_plugin.py → databases/mssql/mssql_db_plugin.py} +3 -3
- databao_context_engine/plugins/databases/{mssql_introspector.py → mssql/mssql_introspector.py} +29 -21
- databao_context_engine/plugins/{mysql_db_plugin.py → databases/mysql/mysql_db_plugin.py} +3 -3
- databao_context_engine/plugins/databases/{mysql_introspector.py → mysql/mysql_introspector.py} +26 -15
- databao_context_engine/plugins/databases/postgresql/__init__.py +0 -0
- databao_context_engine/plugins/databases/postgresql/postgresql_db_plugin.py +15 -0
- databao_context_engine/plugins/databases/{postgresql_introspector.py → postgresql/postgresql_introspector.py} +11 -18
- databao_context_engine/plugins/databases/snowflake/__init__.py +0 -0
- databao_context_engine/plugins/databases/snowflake/snowflake_db_plugin.py +15 -0
- databao_context_engine/plugins/databases/{snowflake_introspector.py → snowflake/snowflake_introspector.py} +49 -17
- databao_context_engine/plugins/databases/sqlite/__init__.py +0 -0
- databao_context_engine/plugins/databases/sqlite/sqlite_db_plugin.py +12 -0
- databao_context_engine/plugins/databases/sqlite/sqlite_introspector.py +241 -0
- databao_context_engine/plugins/duckdb_tools.py +18 -0
- databao_context_engine/plugins/files/__init__.py +0 -0
- databao_context_engine/plugins/{unstructured_files_plugin.py → files/unstructured_files_plugin.py} +1 -1
- databao_context_engine/plugins/plugin_loader.py +58 -52
- databao_context_engine/plugins/resources/parquet_introspector.py +8 -20
- databao_context_engine/plugins/{parquet_plugin.py → resources/parquet_plugin.py} +1 -3
- databao_context_engine/project/info.py +34 -2
- databao_context_engine/project/init_project.py +16 -7
- databao_context_engine/project/layout.py +14 -15
- databao_context_engine/retrieve_embeddings/__init__.py +3 -0
- databao_context_engine/retrieve_embeddings/retrieve_runner.py +17 -0
- databao_context_engine/retrieve_embeddings/{internal/retrieve_service.py → retrieve_service.py} +12 -19
- databao_context_engine/retrieve_embeddings/retrieve_wiring.py +46 -0
- databao_context_engine/serialization/__init__.py +0 -0
- databao_context_engine/{serialisation → serialization}/yaml.py +6 -6
- databao_context_engine/services/chunk_embedding_service.py +23 -11
- databao_context_engine/services/factories.py +1 -46
- databao_context_engine/services/persistence_service.py +11 -11
- databao_context_engine/storage/connection.py +11 -7
- databao_context_engine/storage/exceptions/exceptions.py +2 -2
- databao_context_engine/storage/migrate.py +3 -5
- databao_context_engine/storage/migrations/V01__init.sql +6 -31
- databao_context_engine/storage/models.py +2 -23
- databao_context_engine/storage/repositories/chunk_repository.py +16 -12
- databao_context_engine/storage/repositories/factories.py +1 -12
- databao_context_engine/storage/repositories/vector_search_repository.py +23 -16
- databao_context_engine/system/properties.py +4 -2
- databao_context_engine-0.1.5.dist-info/METADATA +228 -0
- databao_context_engine-0.1.5.dist-info/RECORD +135 -0
- {databao_context_engine-0.1.1.dist-info → databao_context_engine-0.1.5.dist-info}/WHEEL +1 -1
- databao_context_engine/build_sources/internal/build_service.py +0 -77
- databao_context_engine/build_sources/internal/build_wiring.py +0 -52
- databao_context_engine/build_sources/internal/export_results.py +0 -43
- databao_context_engine/build_sources/public/api.py +0 -4
- databao_context_engine/databao_engine.py +0 -85
- databao_context_engine/datasource_config/add_config.py +0 -50
- databao_context_engine/datasource_config/datasource_context.py +0 -60
- databao_context_engine/mcp/all_results_tool.py +0 -5
- databao_context_engine/mcp/retrieve_tool.py +0 -22
- databao_context_engine/plugins/databases/athena_introspector.py +0 -101
- databao_context_engine/plugins/duckdb_db_plugin.py +0 -12
- databao_context_engine/plugins/postgresql_db_plugin.py +0 -12
- databao_context_engine/plugins/snowflake_db_plugin.py +0 -12
- databao_context_engine/project/datasource_discovery.py +0 -141
- databao_context_engine/project/runs.py +0 -39
- databao_context_engine/project/types.py +0 -134
- databao_context_engine/retrieve_embeddings/internal/export_results.py +0 -12
- databao_context_engine/retrieve_embeddings/internal/retrieve_runner.py +0 -34
- databao_context_engine/retrieve_embeddings/internal/retrieve_wiring.py +0 -29
- databao_context_engine/retrieve_embeddings/public/api.py +0 -3
- databao_context_engine/services/run_name_policy.py +0 -8
- databao_context_engine/storage/repositories/datasource_run_repository.py +0 -136
- databao_context_engine/storage/repositories/run_repository.py +0 -157
- databao_context_engine-0.1.1.dist-info/METADATA +0 -186
- databao_context_engine-0.1.1.dist-info/RECORD +0 -135
- /databao_context_engine/{build_sources/internal → datasources}/__init__.py +0 -0
- /databao_context_engine/{build_sources/public → plugins/databases/athena}/__init__.py +0 -0
- /databao_context_engine/{datasource_config → plugins/databases/clickhouse}/__init__.py +0 -0
- /databao_context_engine/{retrieve_embeddings/internal → plugins/databases/duckdb}/__init__.py +0 -0
- /databao_context_engine/{retrieve_embeddings/public → plugins/databases/mssql}/__init__.py +0 -0
- /databao_context_engine/{serialisation → plugins/databases/mysql}/__init__.py +0 -0
- {databao_context_engine-0.1.1.dist-info → databao_context_engine-0.1.5.dist-info}/entry_points.txt +0 -0
|
@@ -6,10 +6,11 @@ from pydantic import BaseModel, ConfigDict, field_validator, model_validator
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ScopeIncludeRule(BaseModel):
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
"""Allowlist selector.
|
|
10
|
+
|
|
11
|
+
Attributes:
|
|
12
|
+
catalog: optional glob pattern
|
|
13
|
+
schemas: optional list of glob patterns (string also accepted and normalized to a list)
|
|
13
14
|
|
|
14
15
|
A rule must specify at least one of: catalog, schemas.
|
|
15
16
|
"""
|
|
@@ -36,11 +37,12 @@ class ScopeIncludeRule(BaseModel):
|
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
class ScopeExcludeRule(BaseModel):
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
"""Denylist selector.
|
|
41
|
+
|
|
42
|
+
Attributes:
|
|
43
|
+
catalog: optional glob pattern
|
|
44
|
+
schemas: optional list of glob patterns (string also accepted)
|
|
45
|
+
except_schemas: optional list of glob patterns (string also accepted)
|
|
44
46
|
|
|
45
47
|
If a target matches the rule but also matches except_schemas, it is NOT excluded by this rule.
|
|
46
48
|
"""
|
|
@@ -10,17 +10,14 @@ from databao_context_engine.plugins.databases.introspection_scope import (
|
|
|
10
10
|
|
|
11
11
|
@dataclass(frozen=True)
|
|
12
12
|
class ScopeSelection:
|
|
13
|
-
"""
|
|
14
|
-
The final catalog+schema scope to introspect.
|
|
15
|
-
"""
|
|
13
|
+
"""The final catalog+schema scope to introspect."""
|
|
16
14
|
|
|
17
15
|
catalogs: list[str]
|
|
18
16
|
schemas_per_catalog: dict[str, list[str]]
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
class IntrospectionScopeMatcher:
|
|
22
|
-
"""
|
|
23
|
-
Applies include/exclude rules (glob matching, case-insensitive) to a discovered set of catalogs/schemas.
|
|
20
|
+
"""Applies include/exclude rules (glob matching, case-insensitive) to a discovered set of catalogs/schemas.
|
|
24
21
|
|
|
25
22
|
Semantics:
|
|
26
23
|
- If include is empty => start from "everything"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from databao_context_engine.plugins.base_db_plugin import BaseDatabasePlugin
|
|
2
|
-
from databao_context_engine.plugins.databases.mssql_introspector import MSSQLConfigFile, MSSQLIntrospector
|
|
1
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabasePlugin
|
|
2
|
+
from databao_context_engine.plugins.databases.mssql.mssql_introspector import MSSQLConfigFile, MSSQLIntrospector
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class MSSQLDbPlugin(BaseDatabasePlugin[MSSQLConfigFile]):
|
|
6
6
|
id = "jetbrains/mssql"
|
|
7
7
|
name = "MSSQL DB Plugin"
|
|
8
|
-
supported = {"
|
|
8
|
+
supported = {"mssql"}
|
|
9
9
|
config_file_type = MSSQLConfigFile
|
|
10
10
|
|
|
11
11
|
def __init__(self):
|
databao_context_engine/plugins/databases/{mssql_introspector.py → mssql/mssql_introspector.py}
RENAMED
|
@@ -1,21 +1,36 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any, Mapping
|
|
3
|
+
from typing import Annotated, Any, Mapping
|
|
4
4
|
|
|
5
5
|
from mssql_python import connect # type: ignore[import-untyped]
|
|
6
|
-
from pydantic import Field
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
-
from databao_context_engine.
|
|
8
|
+
from databao_context_engine.pluginlib.config import ConfigPropertyAnnotation
|
|
9
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabaseConfigFile
|
|
9
10
|
from databao_context_engine.plugins.databases.base_introspector import BaseIntrospector, SQLQuery
|
|
10
11
|
from databao_context_engine.plugins.databases.databases_types import DatabaseSchema, DatabaseTable
|
|
11
12
|
from databao_context_engine.plugins.databases.introspection_model_builder import IntrospectionModelBuilder
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
class MSSQLConnectionProperties(BaseModel):
|
|
16
|
+
host: Annotated[str, ConfigPropertyAnnotation(default_value="localhost", required=True)]
|
|
17
|
+
port: int | None = None
|
|
18
|
+
instance_name: str | None = None
|
|
19
|
+
database: str | None = None
|
|
20
|
+
user: str | None = None
|
|
21
|
+
password: Annotated[str, ConfigPropertyAnnotation(secret=True)]
|
|
22
|
+
encrypt: str | None = None
|
|
23
|
+
additional_properties: dict[str, Any] = {}
|
|
24
|
+
|
|
25
|
+
def to_mssql_kwargs(self) -> dict[str, Any]:
|
|
26
|
+
kwargs = self.model_dump(exclude={"additional_properties"}, exclude_none=True)
|
|
27
|
+
kwargs.update(self.additional_properties)
|
|
28
|
+
return kwargs
|
|
29
|
+
|
|
30
|
+
|
|
14
31
|
class MSSQLConfigFile(BaseDatabaseConfigFile):
|
|
15
|
-
type: str = Field(default="
|
|
16
|
-
connection:
|
|
17
|
-
description="Connection parameters for the Microsoft Server SQL database. It can contain any of the keys supported by the Microsoft Server connection library"
|
|
18
|
-
)
|
|
32
|
+
type: str = Field(default="mssql")
|
|
33
|
+
connection: MSSQLConnectionProperties
|
|
19
34
|
|
|
20
35
|
|
|
21
36
|
class MSSQLIntrospector(BaseIntrospector[MSSQLConfigFile]):
|
|
@@ -40,24 +55,18 @@ class MSSQLIntrospector(BaseIntrospector[MSSQLConfigFile]):
|
|
|
40
55
|
)
|
|
41
56
|
supports_catalogs = True
|
|
42
57
|
|
|
43
|
-
def _connect(self, file_config: MSSQLConfigFile):
|
|
58
|
+
def _connect(self, file_config: MSSQLConfigFile, *, catalog: str | None = None):
|
|
44
59
|
connection = file_config.connection
|
|
45
|
-
if not isinstance(connection, Mapping):
|
|
46
|
-
raise ValueError("Invalid YAML config: 'connection' must be a mapping of connection parameters")
|
|
47
|
-
|
|
48
|
-
connection_string = self._create_connection_string_for_config(connection)
|
|
49
|
-
return connect(connection_string)
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
cfg_for_db["database"] = catalog
|
|
61
|
+
connection_kwargs = connection.to_mssql_kwargs()
|
|
62
|
+
if catalog:
|
|
63
|
+
connection_kwargs["database"] = catalog
|
|
55
64
|
|
|
56
|
-
connection_string = self._create_connection_string_for_config(
|
|
65
|
+
connection_string = self._create_connection_string_for_config(connection_kwargs)
|
|
57
66
|
return connect(connection_string)
|
|
58
67
|
|
|
59
68
|
def _get_catalogs(self, connection, file_config: MSSQLConfigFile) -> list[str]:
|
|
60
|
-
database = file_config.connection.
|
|
69
|
+
database = file_config.connection.database
|
|
61
70
|
if isinstance(database, str) and database:
|
|
62
71
|
return [database]
|
|
63
72
|
|
|
@@ -413,8 +422,7 @@ class MSSQLIntrospector(BaseIntrospector[MSSQLConfigFile]):
|
|
|
413
422
|
"trust_server_certificate": "yes" if file_config.get("trust_server_certificate") else None,
|
|
414
423
|
}
|
|
415
424
|
|
|
416
|
-
|
|
417
|
-
return connection_string
|
|
425
|
+
return ";".join(f"{k}={v}" for k, v in connection_parts.items() if v is not None)
|
|
418
426
|
|
|
419
427
|
def _fetchall_dicts(self, connection, sql: str, params) -> list[dict]:
|
|
420
428
|
with connection.cursor() as cursor:
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from databao_context_engine.plugins.base_db_plugin import BaseDatabasePlugin
|
|
2
|
-
from databao_context_engine.plugins.databases.mysql_introspector import MySQLConfigFile, MySQLIntrospector
|
|
1
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabasePlugin
|
|
2
|
+
from databao_context_engine.plugins.databases.mysql.mysql_introspector import MySQLConfigFile, MySQLIntrospector
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class MySQLDbPlugin(BaseDatabasePlugin[MySQLConfigFile]):
|
|
6
6
|
id = "jetbrains/mysql"
|
|
7
7
|
name = "MySQL DB Plugin"
|
|
8
|
-
supported = {"
|
|
8
|
+
supported = {"mysql"}
|
|
9
9
|
config_file_type = MySQLConfigFile
|
|
10
10
|
|
|
11
11
|
def __init__(self):
|
databao_context_engine/plugins/databases/{mysql_introspector.py → mysql/mysql_introspector.py}
RENAMED
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Annotated, Any
|
|
2
2
|
|
|
3
3
|
import pymysql
|
|
4
|
-
from pydantic import Field
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
from pymysql.constants import CLIENT
|
|
6
6
|
|
|
7
|
-
from databao_context_engine.
|
|
7
|
+
from databao_context_engine.pluginlib.config import ConfigPropertyAnnotation
|
|
8
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabaseConfigFile
|
|
8
9
|
from databao_context_engine.plugins.databases.base_introspector import BaseIntrospector, SQLQuery
|
|
9
10
|
from databao_context_engine.plugins.databases.databases_types import DatabaseSchema, DatabaseTable
|
|
10
11
|
from databao_context_engine.plugins.databases.introspection_model_builder import IntrospectionModelBuilder
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
class MySQLConnectionProperties(BaseModel):
|
|
15
|
+
host: Annotated[str, ConfigPropertyAnnotation(default_value="localhost", required=True)]
|
|
16
|
+
port: int | None = None
|
|
17
|
+
database: str | None = None
|
|
18
|
+
user: str | None = None
|
|
19
|
+
password: Annotated[str, ConfigPropertyAnnotation(secret=True)]
|
|
20
|
+
additional_properties: dict[str, Any] = {}
|
|
21
|
+
|
|
22
|
+
def to_pymysql_kwargs(self) -> dict[str, Any]:
|
|
23
|
+
kwargs = self.model_dump(exclude={"additional_properties"}, exclude_none=True)
|
|
24
|
+
kwargs.update(self.additional_properties)
|
|
25
|
+
return kwargs
|
|
26
|
+
|
|
27
|
+
|
|
13
28
|
class MySQLConfigFile(BaseDatabaseConfigFile):
|
|
14
|
-
connection:
|
|
15
|
-
type: str = Field(default="
|
|
29
|
+
connection: MySQLConnectionProperties
|
|
30
|
+
type: str = Field(default="mysql")
|
|
16
31
|
|
|
17
32
|
|
|
18
33
|
class MySQLIntrospector(BaseIntrospector[MySQLConfigFile]):
|
|
@@ -20,22 +35,18 @@ class MySQLIntrospector(BaseIntrospector[MySQLConfigFile]):
|
|
|
20
35
|
|
|
21
36
|
supports_catalogs = True
|
|
22
37
|
|
|
23
|
-
def _connect(self, file_config: MySQLConfigFile):
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
def _connect(self, file_config: MySQLConfigFile, *, catalog: str | None = None):
|
|
39
|
+
connection_kwargs = file_config.connection.to_pymysql_kwargs()
|
|
40
|
+
|
|
41
|
+
if catalog:
|
|
42
|
+
connection_kwargs["database"] = catalog
|
|
27
43
|
|
|
28
44
|
return pymysql.connect(
|
|
29
|
-
**
|
|
45
|
+
**connection_kwargs,
|
|
30
46
|
cursorclass=pymysql.cursors.DictCursor,
|
|
31
47
|
client_flag=CLIENT.MULTI_STATEMENTS | CLIENT.MULTI_RESULTS,
|
|
32
48
|
)
|
|
33
49
|
|
|
34
|
-
def _connect_to_catalog(self, file_config: MySQLConfigFile, catalog: str):
|
|
35
|
-
cfg = dict(file_config.connection or {})
|
|
36
|
-
cfg["database"] = catalog
|
|
37
|
-
return self._connect(MySQLConfigFile(connection=cfg))
|
|
38
|
-
|
|
39
50
|
def _get_catalogs(self, connection, file_config: MySQLConfigFile) -> list[str]:
|
|
40
51
|
with connection.cursor() as cur:
|
|
41
52
|
cur.execute(
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabasePlugin
|
|
2
|
+
from databao_context_engine.plugins.databases.postgresql.postgresql_introspector import (
|
|
3
|
+
PostgresConfigFile,
|
|
4
|
+
PostgresqlIntrospector,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PostgresqlDbPlugin(BaseDatabasePlugin[PostgresConfigFile]):
|
|
9
|
+
id = "jetbrains/postgres"
|
|
10
|
+
name = "PostgreSQL DB Plugin"
|
|
11
|
+
supported = {"postgres"}
|
|
12
|
+
config_file_type = PostgresConfigFile
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__(PostgresqlIntrospector())
|
|
@@ -5,7 +5,7 @@ import asyncpg
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
from databao_context_engine.pluginlib.config import ConfigPropertyAnnotation
|
|
8
|
-
from databao_context_engine.plugins.base_db_plugin import BaseDatabaseConfigFile
|
|
8
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabaseConfigFile
|
|
9
9
|
from databao_context_engine.plugins.databases.base_introspector import BaseIntrospector, SQLQuery
|
|
10
10
|
from databao_context_engine.plugins.databases.databases_types import DatabaseSchema
|
|
11
11
|
from databao_context_engine.plugins.databases.introspection_model_builder import IntrospectionModelBuilder
|
|
@@ -16,12 +16,12 @@ class PostgresConnectionProperties(BaseModel):
|
|
|
16
16
|
port: int | None = None
|
|
17
17
|
database: str | None = None
|
|
18
18
|
user: str | None = None
|
|
19
|
-
password: str
|
|
19
|
+
password: Annotated[str, ConfigPropertyAnnotation(secret=True)]
|
|
20
20
|
additional_properties: dict[str, Any] = {}
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class PostgresConfigFile(BaseDatabaseConfigFile):
|
|
24
|
-
type: str = Field(default="
|
|
24
|
+
type: str = Field(default="postgres")
|
|
25
25
|
connection: PostgresConnectionProperties
|
|
26
26
|
|
|
27
27
|
|
|
@@ -81,12 +81,14 @@ class PostgresqlIntrospector(BaseIntrospector[PostgresConfigFile]):
|
|
|
81
81
|
if self.supports_catalogs:
|
|
82
82
|
sql = "SELECT catalog_name, schema_name FROM information_schema.schemata WHERE catalog_name = ANY($1)"
|
|
83
83
|
return SQLQuery(sql, (catalogs,))
|
|
84
|
-
else:
|
|
85
|
-
sql = "SELECT schema_name FROM information_schema.schemata"
|
|
86
|
-
return SQLQuery(sql, None)
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
sql = "SELECT schema_name FROM information_schema.schemata"
|
|
86
|
+
return SQLQuery(sql, None)
|
|
87
|
+
|
|
88
|
+
def _connect(self, file_config: PostgresConfigFile, *, catalog: str | None = None):
|
|
89
89
|
kwargs = self._create_connection_kwargs(file_config.connection)
|
|
90
|
+
if catalog:
|
|
91
|
+
kwargs["database"] = catalog
|
|
90
92
|
return _SyncAsyncpgConnection(kwargs)
|
|
91
93
|
|
|
92
94
|
def _fetchall_dicts(self, connection: _SyncAsyncpgConnection, sql: str, params) -> list[dict]:
|
|
@@ -97,13 +99,7 @@ class PostgresqlIntrospector(BaseIntrospector[PostgresConfigFile]):
|
|
|
97
99
|
if database is not None:
|
|
98
100
|
return [database]
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
return rows
|
|
102
|
-
|
|
103
|
-
def _connect_to_catalog(self, file_config: PostgresConfigFile, catalog: str):
|
|
104
|
-
cfg = file_config.model_copy(deep=True)
|
|
105
|
-
cfg.connection.database = catalog
|
|
106
|
-
return self._connect(cfg)
|
|
102
|
+
return connection.fetch_scalar_values("SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false")
|
|
107
103
|
|
|
108
104
|
def collect_catalog_model(
|
|
109
105
|
self, connection: _SyncAsyncpgConnection, catalog: str, schemas: list[str]
|
|
@@ -408,10 +404,7 @@ class PostgresqlIntrospector(BaseIntrospector[PostgresConfigFile]):
|
|
|
408
404
|
}
|
|
409
405
|
connection_parts.update(connection_config.additional_properties)
|
|
410
406
|
|
|
411
|
-
|
|
412
|
-
f"{k}={_escape_pg_value(str(v))}" for k, v in connection_parts.items() if v is not None
|
|
413
|
-
)
|
|
414
|
-
return connection_string
|
|
407
|
+
return " ".join(f"{k}={_escape_pg_value(str(v))}" for k, v in connection_parts.items() if v is not None)
|
|
415
408
|
|
|
416
409
|
def _create_connection_kwargs(self, connection_config: PostgresConnectionProperties) -> dict[str, Any]:
|
|
417
410
|
kwargs: dict[str, Any] = {
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabasePlugin
|
|
2
|
+
from databao_context_engine.plugins.databases.snowflake.snowflake_introspector import (
|
|
3
|
+
SnowflakeConfigFile,
|
|
4
|
+
SnowflakeIntrospector,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SnowflakeDbPlugin(BaseDatabasePlugin[SnowflakeConfigFile]):
|
|
9
|
+
id = "jetbrains/snowflake"
|
|
10
|
+
name = "Snowflake DB Plugin"
|
|
11
|
+
supported = {"snowflake"}
|
|
12
|
+
config_file_type = SnowflakeConfigFile
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__(SnowflakeIntrospector())
|
|
@@ -1,22 +1,57 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict, List
|
|
3
|
+
from typing import Annotated, Any, Dict, List
|
|
4
4
|
|
|
5
5
|
import snowflake.connector
|
|
6
|
-
from pydantic import Field
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
7
|
from snowflake.connector import DictCursor
|
|
8
8
|
|
|
9
|
-
from databao_context_engine.
|
|
9
|
+
from databao_context_engine.pluginlib.config import ConfigPropertyAnnotation
|
|
10
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabaseConfigFile
|
|
10
11
|
from databao_context_engine.plugins.databases.base_introspector import BaseIntrospector, SQLQuery
|
|
11
12
|
from databao_context_engine.plugins.databases.databases_types import DatabaseSchema
|
|
12
13
|
from databao_context_engine.plugins.databases.introspection_model_builder import IntrospectionModelBuilder
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
class SnowflakePasswordAuth(BaseModel):
|
|
17
|
+
password: Annotated[str, ConfigPropertyAnnotation(secret=True)]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SnowflakeKeyPairAuth(BaseModel):
|
|
21
|
+
private_key_file: str | None = None
|
|
22
|
+
private_key_file_pwd: str | None = None
|
|
23
|
+
private_key: Annotated[str | None, ConfigPropertyAnnotation(secret=True)] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SnowflakeSSOAuth(BaseModel):
|
|
27
|
+
authenticator: str = Field(description='e.g. "externalbrowser"')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SnowflakeConnectionProperties(BaseModel):
|
|
31
|
+
account: Annotated[str, ConfigPropertyAnnotation(required=True)]
|
|
32
|
+
warehouse: str | None = None
|
|
33
|
+
database: str | None = None
|
|
34
|
+
user: str | None = None
|
|
35
|
+
role: str | None = None
|
|
36
|
+
auth: SnowflakePasswordAuth | SnowflakeKeyPairAuth | SnowflakeSSOAuth
|
|
37
|
+
additional_properties: dict[str, Any] = {}
|
|
38
|
+
|
|
39
|
+
def to_snowflake_kwargs(self) -> dict[str, Any]:
|
|
40
|
+
kwargs = self.model_dump(
|
|
41
|
+
exclude={
|
|
42
|
+
"additional_properties": True,
|
|
43
|
+
},
|
|
44
|
+
exclude_none=True,
|
|
45
|
+
)
|
|
46
|
+
auth_fields = kwargs.pop("auth", {})
|
|
47
|
+
kwargs.update(auth_fields)
|
|
48
|
+
kwargs.update(self.additional_properties)
|
|
49
|
+
return kwargs
|
|
50
|
+
|
|
51
|
+
|
|
15
52
|
class SnowflakeConfigFile(BaseDatabaseConfigFile):
|
|
16
|
-
type: str = Field(default="
|
|
17
|
-
connection:
|
|
18
|
-
description="Connection parameters for Snowflake. It can contain any of the keys supported by the Snowflake connection library"
|
|
19
|
-
)
|
|
53
|
+
type: str = Field(default="snowflake")
|
|
54
|
+
connection: SnowflakeConnectionProperties
|
|
20
55
|
|
|
21
56
|
|
|
22
57
|
class SnowflakeIntrospector(BaseIntrospector[SnowflakeConfigFile]):
|
|
@@ -26,22 +61,19 @@ class SnowflakeIntrospector(BaseIntrospector[SnowflakeConfigFile]):
|
|
|
26
61
|
_IGNORED_CATALOGS = {"STREAMLIT_APPS"}
|
|
27
62
|
supports_catalogs = True
|
|
28
63
|
|
|
29
|
-
def _connect(self, file_config: SnowflakeConfigFile):
|
|
64
|
+
def _connect(self, file_config: SnowflakeConfigFile, *, catalog: str | None = None):
|
|
30
65
|
connection = file_config.connection
|
|
31
|
-
if not isinstance(connection, Mapping):
|
|
32
|
-
raise ValueError("Invalid YAML config: 'connection' must be a mapping of connection parameters")
|
|
33
66
|
snowflake.connector.paramstyle = "qmark"
|
|
67
|
+
connection_kwargs = connection.to_snowflake_kwargs()
|
|
68
|
+
if catalog:
|
|
69
|
+
connection_kwargs["database"] = catalog
|
|
70
|
+
|
|
34
71
|
return snowflake.connector.connect(
|
|
35
|
-
**
|
|
72
|
+
**connection_kwargs,
|
|
36
73
|
)
|
|
37
74
|
|
|
38
|
-
def _connect_to_catalog(self, file_config: SnowflakeConfigFile, catalog: str):
|
|
39
|
-
cfg = dict(file_config.connection or {})
|
|
40
|
-
cfg["database"] = catalog
|
|
41
|
-
return snowflake.connector.connect(**cfg)
|
|
42
|
-
|
|
43
75
|
def _get_catalogs(self, connection, file_config: SnowflakeConfigFile) -> list[str]:
|
|
44
|
-
database = file_config.connection.
|
|
76
|
+
database = file_config.connection.database
|
|
45
77
|
if database:
|
|
46
78
|
return [database]
|
|
47
79
|
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from databao_context_engine.plugins.databases.base_db_plugin import BaseDatabasePlugin
|
|
2
|
+
from databao_context_engine.plugins.databases.sqlite.sqlite_introspector import SQLiteConfigFile, SQLiteIntrospector
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SQLiteDbPlugin(BaseDatabasePlugin[SQLiteConfigFile]):
|
|
6
|
+
id = "jetbrains/sqlite"
|
|
7
|
+
name = "SQLite Plugin"
|
|
8
|
+
supported = {"sqlite"}
|
|
9
|
+
config_file_type = SQLiteConfigFile
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
super().__init__(SQLiteIntrospector())
|