SQL implementation of the storage client. This storage client provides access to datasets, key-value stores, and request queues that persist data to a SQL database using SQLAlchemy 2+. Each storage type uses two tables: one for metadata and one for records. The client accepts eithe
| 33 | |
| 34 | @docs_group('Storage clients') |
| 35 | class SqlStorageClient(StorageClient): |
| 36 | """SQL implementation of the storage client. |
| 37 | |
| 38 | This storage client provides access to datasets, key-value stores, and request queues that persist data |
| 39 | to a SQL database using SQLAlchemy 2+. Each storage type uses two tables: one for metadata and one for |
| 40 | records. |
| 41 | |
| 42 | The client accepts either a database connection string or a pre-configured AsyncEngine. If neither is |
| 43 | provided, it creates a default SQLite database 'crawlee.db' in the storage directory. |
| 44 | |
| 45 | Database schema is automatically created during initialization. SQLite databases receive performance |
| 46 | optimizations including WAL mode and increased cache size. |
| 47 | |
| 48 | Warning: |
| 49 | This is an experimental feature. The behavior and interface may change in future versions. |
| 50 | """ |
| 51 | |
| 52 | _DEFAULT_DB_NAME = 'crawlee.db' |
| 53 | """Default database name if not specified in connection string.""" |
| 54 | |
| 55 | _SUPPORTED_DIALECTS: ClassVar[set[str]] = {'sqlite', 'postgresql', 'mysql', 'mariadb'} |
| 56 | |
| 57 | def __init__( |
| 58 | self, |
| 59 | *, |
| 60 | connection_string: str | None = None, |
| 61 | engine: AsyncEngine | None = None, |
| 62 | ) -> None: |
| 63 | """Initialize the SQL storage client. |
| 64 | |
| 65 | Args: |
| 66 | connection_string: Database connection string (e.g., "sqlite+aiosqlite:///crawlee.db"). |
| 67 | If not provided, defaults to SQLite database in the storage directory. |
| 68 | engine: Pre-configured AsyncEngine instance. If provided, connection_string is ignored. |
| 69 | """ |
| 70 | if engine is not None and connection_string is not None: |
| 71 | raise ValueError('Either connection_string or engine must be provided, not both.') |
| 72 | |
| 73 | self._connection_string = connection_string |
| 74 | self._engine = engine |
| 75 | self._initialized = False |
| 76 | self.session_maker: None | async_sessionmaker[AsyncSession] = None |
| 77 | |
| 78 | self._listeners_registered = False |
| 79 | self._dialect_name: str | None = None |
| 80 | |
| 81 | # Call the notification only once |
| 82 | warnings.warn( |
| 83 | 'The SqlStorageClient is experimental and may change or be removed in future releases.', |
| 84 | category=UserWarning, |
| 85 | stacklevel=2, |
| 86 | ) |
| 87 | |
| 88 | async def __aenter__(self) -> SqlStorageClient: |
| 89 | """Async context manager entry.""" |
| 90 | return self |
| 91 | |
| 92 | async def __aexit__( |
no outgoing calls