Source code for sqlalchemy_jdbcapi.dialects.postgresql

"""
PostgreSQL JDBC dialect for SQLAlchemy.

Provides full PostgreSQL support through JDBC, compatible with SQLAlchemy 2.0+.
"""

from __future__ import annotations

import logging
import re
from typing import Any

from sqlalchemy import sql
from sqlalchemy.dialects.postgresql.base import PGDialect
from sqlalchemy.engine import Connection

from .base import BaseJDBCDialect, JDBCDriverConfig

logger = logging.getLogger(__name__)


[docs] class PostgreSQLDialect(BaseJDBCDialect, PGDialect): """ PostgreSQL dialect using JDBC driver. Supports all PostgreSQL-specific features including: - Arrays - JSONB - UUID - Full-text search - Custom types Connection URL format: jdbcapi+postgresql://user:password@host:5432/database jdbcapi+pgjdbc://user:password@host:5432/database # Alias """ name = "postgresql" driver = "jdbcapi" # PostgreSQL-specific capabilities supports_native_enum = True supports_sequences = True supports_native_boolean = True supports_smallserial = True supports_statement_cache = True # Column specifications inherited from PGDialect # Can be extended in the future for JDBC-specific type mappings if needed
[docs] @classmethod def get_driver_config(cls) -> JDBCDriverConfig: """Get PostgreSQL JDBC driver configuration.""" return JDBCDriverConfig( driver_class="org.postgresql.Driver", jdbc_url_template="jdbc:postgresql://{host}:{port}/{database}", default_port=5432, supports_transactions=True, supports_schemas=True, supports_sequences=True, )
[docs] def initialize(self, connection: Connection) -> None: """Initialize PostgreSQL connection.""" super().initialize(connection) # Set up PostgreSQL-specific settings logger.debug("Initialized PostgreSQL JDBC dialect")
def _get_server_version_info(self, connection: Connection) -> tuple[int, ...]: """ Get PostgreSQL server version. Returns: Tuple of version numbers (e.g., (14, 5, 0)) """ try: result = connection.execute(sql.text("SELECT version()")).scalar() if result: # Parse version from string like: # "PostgreSQL 14.5 on x86_64-pc-linux-gnu..." match = re.search(r"PostgreSQL (\d+)\.(\d+)(?:\.(\d+))?", result) if match: major = int(match.group(1)) minor = int(match.group(2)) patch = int(match.group(3)) if match.group(3) else 0 return (major, minor, patch) except Exception as e: logger.warning(f"Failed to get server version: {e}") # Default fallback return (9, 0, 0)
[docs] def do_ping(self, dbapi_connection: Any) -> bool: """ Check if PostgreSQL connection is alive. Uses a simple SELECT query for efficiency. """ try: cursor = dbapi_connection.cursor() cursor.execute("SELECT 1") cursor.close() return True except Exception as e: logger.debug(f"PostgreSQL ping failed: {e}") return False
# Export the dialect dialect = PostgreSQLDialect