Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/logging-execution" # NOSONAR
pip install git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17#egg=rhosocial-activerecord-testsuite

- name: Install package
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/logging-execution" # NOSONAR
pip install git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17#egg=rhosocial-activerecord-testsuite

- name: Install package
Expand Down Expand Up @@ -117,7 +117,7 @@ jobs:
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/logging-execution" # NOSONAR
pip install git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17#egg=rhosocial-activerecord-testsuite

- name: Install package
Expand Down
1 change: 1 addition & 0 deletions changelog.d/11.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adapted this backend to the core execution logging contract: structured execution summaries, shared sync/async logger ownership, redacted SQL logging, and bridges for the shared relation/query/basic contracts.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# src/rhosocial/activerecord/backend/impl/snowflake/async_transaction.py
"""Snowflake asynchronous transaction manager implementation.

This module provides async transaction management for the Snowflake backend.
Snowflake only supports READ COMMITTED isolation level.
"""
import logging
from typing import TYPE_CHECKING

from rhosocial.activerecord.backend.transaction import AsyncTransactionManager
Expand Down Expand Up @@ -41,5 +41,5 @@ async def _do_begin(self) -> None:
READ COMMITTED.
"""
sql, params = self._build_begin_sql()
self.log(logging.DEBUG, f"Executing: {sql}")
# The backend execution path owns the canonical DEBUG SQL record.
await self._backend.execute(sql, params)
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# src/rhosocial/activerecord/backend/impl/snowflake/backend/async_backend.py
"""Snowflake asynchronous backend implementation.

This module provides the async Snowflake backend using a thread pool
Expand Down Expand Up @@ -26,7 +27,7 @@
import asyncio
import logging
from concurrent.futures import Executor
from typing import Any, Dict, Optional, Tuple
from typing import Optional, Tuple

from rhosocial.activerecord.backend.base import AsyncStorageBackend
from rhosocial.activerecord.backend.errors import (
Expand All @@ -39,7 +40,6 @@
from rhosocial.activerecord.backend.introspection.backend_mixin import IntrospectorBackendMixin
from ..config import SnowflakeConnectionConfig
from ..dialect import SnowflakeDialect
from ..async_transaction import AsyncSnowflakeTransactionManager
from ..mixins import SnowflakeBackendMixin, AsyncSnowflakeConcurrencyMixin


Expand Down Expand Up @@ -190,19 +190,19 @@ async def _handle_error(self, error: Exception) -> None:
category = self._classify_error(error)
error_msg = str(error)
if category == 'connection':
self.log(logging.ERROR, f"Connection error: {error_msg}")
self.log(logging.DEBUG, f"Connection error: {error_msg}")
raise ConnectionError(error_msg) from error
elif category == 'integrity':
self.log(logging.ERROR, f"Integrity error: {error_msg}")
self.log(logging.DEBUG, f"Integrity error: {error_msg}")
raise IntegrityError(error_msg) from error
elif category == 'query':
self.log(logging.ERROR, f"Query error: {error_msg}")
self.log(logging.DEBUG, f"Query error: {error_msg}")
raise QueryError(error_msg) from error
elif category == 'operational':
self.log(logging.ERROR, f"Operational error: {error_msg}")
self.log(logging.DEBUG, f"Operational error: {error_msg}")
raise OperationalError(error_msg) from error
else:
self.log(logging.ERROR, f"Database error: {error_msg}")
self.log(logging.DEBUG, f"Database error: {error_msg}")
raise DatabaseError(error_msg) from error

async def get_server_version(self) -> Tuple[int, ...]:
Expand Down Expand Up @@ -260,7 +260,7 @@ async def _process_result_set(self, cursor, is_select, column_adapters=None, col
final_results.append(final_row)
return final_results
except Exception as e:
self.logger.error(f"Error processing async result set: {str(e)}", exc_info=True)
self.log(logging.DEBUG, f"Error processing async result set: {str(e)}")
raise

def _create_introspector(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# src/rhosocial/activerecord/backend/impl/snowflake/backend/backend.py
"""Snowflake synchronous backend implementation.

This module provides the concrete implementation for interacting with Snowflake databases,
handling connections, queries, transactions, and type adaptations tailored for Snowflake's
specific behaviors and SQL dialect.
"""
import logging
from typing import Any, Dict, List, Optional, Tuple
from typing import Tuple

from rhosocial.activerecord.backend.base import StorageBackend
from rhosocial.activerecord.backend.errors import (
Expand All @@ -15,11 +16,9 @@
OperationalError,
QueryError,
)
from rhosocial.activerecord.backend.result import QueryResult
from rhosocial.activerecord.backend.introspection.backend_mixin import IntrospectorBackendMixin
from ..config import SnowflakeConnectionConfig
from ..dialect import SnowflakeDialect
from ..transaction import SnowflakeTransactionManager
from ..mixins import SnowflakeBackendMixin, SnowflakeConcurrencyMixin


Expand Down Expand Up @@ -158,19 +157,19 @@ def _handle_error(self, error: Exception) -> None:
category = self._classify_error(error)
error_msg = str(error)
if category == 'connection':
self.log(logging.ERROR, f"Connection error: {error_msg}")
self.log(logging.DEBUG, f"Connection error: {error_msg}")
raise ConnectionError(error_msg) from error
elif category == 'integrity':
self.log(logging.ERROR, f"Integrity error: {error_msg}")
self.log(logging.DEBUG, f"Integrity error: {error_msg}")
raise IntegrityError(error_msg) from error
elif category == 'query':
self.log(logging.ERROR, f"Query error: {error_msg}")
self.log(logging.DEBUG, f"Query error: {error_msg}")
raise QueryError(error_msg) from error
elif category == 'operational':
self.log(logging.ERROR, f"Operational error: {error_msg}")
self.log(logging.DEBUG, f"Operational error: {error_msg}")
raise OperationalError(error_msg) from error
else:
self.log(logging.ERROR, f"Database error: {error_msg}")
self.log(logging.DEBUG, f"Database error: {error_msg}")
raise DatabaseError(error_msg) from error

def get_server_version(self) -> Tuple[int, ...]:
Expand Down Expand Up @@ -296,7 +295,7 @@ def _process_result_set(self, cursor, is_select, column_adapters=None, column_ma
final_results.append(final_row)
return final_results
except Exception as e:
self.logger.error(f"Error processing result set: {str(e)}", exc_info=True)
self.log(logging.DEBUG, f"Error processing result set: {str(e)}")
raise

def _create_introspector(self):
Expand Down
11 changes: 7 additions & 4 deletions src/rhosocial/activerecord/backend/impl/snowflake/cli/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import argparse
import inspect
import json
import logging
from typing import Any, Dict, List, Tuple

from rhosocial.activerecord.backend.dialect.protocols import (
Expand All @@ -28,11 +27,12 @@
SnowflakeCloneSupport,
SnowflakeStageSupport,
)
from rhosocial.activerecord.logging.defaults import get_logger

from .connection import add_connection_args, add_version_arg, resolve_connection_config_from_args
from .output import INFO_OUTPUT_CHOICES, create_provider, RICH_AVAILABLE

logger = logging.getLogger(__name__)
logger = get_logger("rhosocial.activerecord.backend.snowflake")

DIALECT_SPECIFIC_GROUPS = {"Snowflake-specific"}

Expand Down Expand Up @@ -112,7 +112,7 @@ def create_parser(subparsers):

def handle(args):
"""Handle the info subcommand."""
provider = create_provider(args.output, ascii_borders=args.rich_ascii)
create_provider(args.output, ascii_borders=args.rich_ascii)

is_connected = False
dialect = None
Expand Down Expand Up @@ -349,7 +349,10 @@ def _display_info_rich(info: Dict, verbose: int, version_display: str, is_connec
if is_connected:
console.print(f"[bold]Snowflake Version:[/bold] {version_display} [dim](from actual connection)[/dim]\n")
else:
console.print(f"[bold]Snowflake Version:[/bold] {version_display} [yellow](default value - no database connection)[/yellow]\n")
console.print(
f"[bold]Snowflake Version:[/bold] {version_display} "
"[yellow](default value - no database connection)[/yellow]\n"
)

label = "Detailed" if verbose >= 2 else "Family Overview"
console.print(f"[bold green]Protocol Support ({label}):[/bold green]")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ class SnowflakeBackendMixin:
and dialect property management.
"""

def _get_logger_name(self) -> str:
"""Return the canonical Snowflake backend logger name.

Both the synchronous and asynchronous backends use the same library
logger, so application logging configuration has one name to target.
"""
return "rhosocial.activerecord.backend.snowflake"

def _register_snowflake_adapters(self) -> None:
"""Register Snowflake-specific type adapters."""
adapters = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# src/rhosocial/activerecord/backend/impl/snowflake/transaction.py
"""Snowflake synchronous transaction manager implementation.

This module provides Snowflake-specific transaction management.
Snowflake only supports READ COMMITTED isolation level.
"""
import logging
from typing import TYPE_CHECKING

from rhosocial.activerecord.backend.transaction import TransactionManager
Expand Down Expand Up @@ -41,5 +41,5 @@ def _do_begin(self) -> None:
READ COMMITTED.
"""
sql, params = self._build_begin_sql()
self.log(logging.DEBUG, f"Executing: {sql}")
# The backend execution path owns the canonical DEBUG SQL record.
self._backend.execute(sql, params)
Loading
Loading