iris-pgwire 1.2.29__tar.gz → 1.2.30__tar.gz

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.
Files changed (111) hide show
  1. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/PKG-INFO +1 -1
  2. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/__init__.py +1 -1
  3. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/scram.py +10 -11
  4. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/backend_selector.py +24 -31
  5. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/catalog_router.py +3 -2
  6. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/dbapi_connection_pool.py +41 -46
  7. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/dbapi_executor.py +33 -46
  8. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/api.py +2 -2
  9. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/debug.py +9 -15
  10. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/identifier_normalizer.py +6 -20
  11. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/interceptor.py +3 -2
  12. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/pipeline.py +2 -2
  13. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/refiner.py +3 -2
  14. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/translator.py +0 -4
  15. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/validator.py +3 -2
  16. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/vector_optimizer.py +3 -2
  17. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/.gitignore +0 -0
  18. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/CHANGELOG.md +0 -0
  19. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/LICENSE +0 -0
  20. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/README.md +0 -0
  21. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/docs/VECTOR_PARAMETER_BINDING.md +0 -0
  22. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/BI_TOOLS_SETUP.md +0 -0
  23. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/async_sqlalchemy_demo.py +0 -0
  24. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/bi_tools_demo.py +0 -0
  25. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/client_demonstrations.py +0 -0
  26. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/client_demos.py +0 -0
  27. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/examples/translation_api_demo.py +0 -0
  28. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/pyproject.toml +0 -0
  29. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/__init__.py +0 -0
  30. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/auth_selector.py +0 -0
  31. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/gssapi_auth.py +0 -0
  32. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/oauth_bridge.py +0 -0
  33. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/auth/wallet_credentials.py +0 -0
  34. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/bulk_executor.py +0 -0
  35. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/__init__.py +0 -0
  36. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/catalog_functions.py +0 -0
  37. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/oid_generator.py +0 -0
  38. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_attrdef.py +0 -0
  39. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_attribute.py +0 -0
  40. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_class.py +0 -0
  41. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_constraint.py +0 -0
  42. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_index.py +0 -0
  43. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_namespace.py +0 -0
  44. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/catalog/pg_type.py +0 -0
  45. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/column_validator.py +0 -0
  46. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/config_schema.py +0 -0
  47. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/constitutional.py +0 -0
  48. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/__init__.py +0 -0
  49. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/bulk_insert.py +0 -0
  50. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/date_horolog.py +0 -0
  51. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/ddl_idempotency.py +0 -0
  52. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/ddl_splitter.py +0 -0
  53. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/json_path.py +0 -0
  54. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/conversions/vector_syntax.py +0 -0
  55. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/copy_handler.py +0 -0
  56. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/csv_processor.py +0 -0
  57. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/debug_tracer.py +0 -0
  58. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/health_checker.py +0 -0
  59. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/integratedml.py +0 -0
  60. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/iris_constructs.py +0 -0
  61. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/iris_executor.py +0 -0
  62. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/iris_log_handler.py +0 -0
  63. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/iris_user_management.py +0 -0
  64. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/__init__.py +0 -0
  65. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/backend_config.py +0 -0
  66. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/connection_pool_state.py +0 -0
  67. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/dbapi_connection.py +0 -0
  68. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/ipm_metadata.py +0 -0
  69. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/models/vector_query_request.py +0 -0
  70. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/observability.py +0 -0
  71. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/performance_monitor.py +0 -0
  72. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/protocol.py +0 -0
  73. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/__init__.py +0 -0
  74. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/__main__.py +0 -0
  75. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/code_quality_validator.py +0 -0
  76. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/documentation_validator.py +0 -0
  77. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/package_metadata_validator.py +0 -0
  78. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/security_validator.py +0 -0
  79. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/quality/validator.py +0 -0
  80. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/schema_mapper.py +0 -0
  81. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/server.py +0 -0
  82. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/__init__.py +0 -0
  83. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/alias_extractor.py +0 -0
  84. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/boolean_translator.py +0 -0
  85. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/cache.py +0 -0
  86. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/confidence_analyzer.py +0 -0
  87. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/config.py +0 -0
  88. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/copy_parser.py +0 -0
  89. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/date_translator.py +0 -0
  90. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/default_values.py +0 -0
  91. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/enum_registry.py +0 -0
  92. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/enum_translator.py +0 -0
  93. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/error_handler.py +0 -0
  94. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/logging_config.py +0 -0
  95. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/mappings/__init__.py +0 -0
  96. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/mappings/constructs.py +0 -0
  97. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/mappings/datatypes.py +0 -0
  98. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/mappings/document_filters.py +0 -0
  99. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/mappings/functions.py +0 -0
  100. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/metrics.py +0 -0
  101. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/models.py +0 -0
  102. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/normalizer.py +0 -0
  103. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/parser.py +0 -0
  104. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/performance_monitor.py +0 -0
  105. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/skipped_table_set.py +0 -0
  106. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/statement_filter.py +0 -0
  107. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/sql_translator/transaction_translator.py +0 -0
  108. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/testing/__init__.py +0 -0
  109. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/testing/base_fixture_builder.py +0 -0
  110. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/type_mapping.py +0 -0
  111. {iris_pgwire-1.2.29 → iris_pgwire-1.2.30}/src/iris_pgwire/vector_metrics.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-pgwire
3
- Version: 1.2.29
3
+ Version: 1.2.30
4
4
  Summary: PostgreSQL Wire Protocol Server for InterSystems IRIS - Connect BI tools, Python frameworks, and PostgreSQL clients to IRIS databases
5
5
  Project-URL: Homepage, https://github.com/intersystems-community/iris-pgwire
6
6
  Project-URL: Documentation, https://github.com/intersystems-community/iris-pgwire#readme
@@ -6,7 +6,7 @@ Based on the specification from docs/iris_pgwire_plan.md and proven patterns fro
6
6
  caretdev/sqlalchemy-iris.
7
7
  """
8
8
 
9
- __version__ = "1.2.29"
9
+ __version__ = "1.2.30"
10
10
  __author__ = "Thomas Dyar <thomas.dyar@intersystems.com>"
11
11
 
12
12
  # Don't import server/protocol in __init__ to avoid sys.modules conflicts
@@ -17,7 +17,7 @@ import asyncio
17
17
  import base64
18
18
  import hashlib
19
19
  import hmac
20
- import logging
20
+ import re
21
21
  import secrets
22
22
  import struct
23
23
  import time
@@ -30,8 +30,7 @@ import structlog
30
30
  from iris_pgwire.constitutional import get_governor
31
31
  from iris_pgwire.performance_monitor import get_monitor
32
32
 
33
- logger = logging.getLogger(__name__)
34
- structured_logger = structlog.get_logger(__name__)
33
+ logger = structlog.get_logger(__name__)
35
34
 
36
35
 
37
36
  class AuthenticationState(Enum):
@@ -98,7 +97,7 @@ class IRISAuthenticationProvider:
98
97
  governor = get_governor()
99
98
 
100
99
  # Log authentication attempt with constitutional monitoring
101
- structured_logger.info(
100
+ logger.info(
102
101
  "IRIS authentication attempt initiated",
103
102
  username=username,
104
103
  constitutional_compliance_enabled=True,
@@ -146,7 +145,7 @@ class IRISAuthenticationProvider:
146
145
  )
147
146
 
148
147
  # Log constitutional compliance status
149
- structured_logger.info(
148
+ logger.info(
150
149
  "IRIS authentication completed",
151
150
  username=username,
152
151
  auth_time_ms=auth_time,
@@ -156,7 +155,7 @@ class IRISAuthenticationProvider:
156
155
  )
157
156
 
158
157
  if not sla_compliant:
159
- structured_logger.warning(
158
+ logger.warning(
160
159
  "Constitutional SLA violation in authentication",
161
160
  username=username,
162
161
  auth_time_ms=auth_time,
@@ -176,7 +175,7 @@ class IRISAuthenticationProvider:
176
175
  operation="iris_authentication", duration_ms=auth_time, success=False
177
176
  )
178
177
 
179
- structured_logger.error(
178
+ logger.error(
180
179
  "IRIS authentication error", username=username, error=str(e), auth_time_ms=auth_time
181
180
  )
182
181
  return False, None
@@ -431,7 +430,7 @@ class PostgreSQLAuthenticator:
431
430
  governor = get_governor()
432
431
 
433
432
  # Log authentication attempt with constitutional monitoring
434
- structured_logger.info(
433
+ logger.info(
435
434
  "PostgreSQL authentication initiated",
436
435
  connection_id=connection_id,
437
436
  username=username,
@@ -464,7 +463,7 @@ class PostgreSQLAuthenticator:
464
463
  )
465
464
 
466
465
  # Log constitutional compliance status
467
- structured_logger.info(
466
+ logger.info(
468
467
  "PostgreSQL authentication completed",
469
468
  connection_id=connection_id,
470
469
  username=username,
@@ -476,7 +475,7 @@ class PostgreSQLAuthenticator:
476
475
  )
477
476
 
478
477
  if not result.sla_compliant:
479
- structured_logger.warning(
478
+ logger.warning(
480
479
  "Constitutional SLA violation in PostgreSQL authentication",
481
480
  connection_id=connection_id,
482
481
  username=username,
@@ -498,7 +497,7 @@ class PostgreSQLAuthenticator:
498
497
  operation="postgresql_authentication", duration_ms=auth_time, success=False
499
498
  )
500
499
 
501
- structured_logger.error(
500
+ logger.error(
502
501
  "PostgreSQL authentication error",
503
502
  connection_id=connection_id,
504
503
  username=username,
@@ -12,12 +12,13 @@ Feature: 018-add-dbapi-option
12
12
  Contract: contracts/backend-selector-contract.md
13
13
  """
14
14
 
15
- import logging
16
15
  from typing import Any, Protocol
17
16
 
17
+ import structlog
18
+
18
19
  from iris_pgwire.models.backend_config import BackendConfig, BackendType
19
20
 
20
- logger = logging.getLogger(__name__)
21
+ logger = structlog.get_logger(__name__)
21
22
 
22
23
 
23
24
  class Executor(Protocol):
@@ -125,19 +126,17 @@ class BackendSelector:
125
126
 
126
127
  logger.info(
127
128
  "Selecting backend executor",
128
- extra={
129
- "backend_type": backend_type.value,
130
- "requires_pool": config.requires_pool(),
131
- "pool_config": (
132
- {
133
- "size": config.pool_size,
134
- "overflow": config.pool_max_overflow,
135
- "total": config.total_connections(),
136
- }
137
- if config.requires_pool()
138
- else None
139
- ),
140
- },
129
+ backend_type=backend_type.value,
130
+ requires_pool=config.requires_pool(),
131
+ pool_config=(
132
+ {
133
+ "size": config.pool_size,
134
+ "overflow": config.pool_max_overflow,
135
+ "total": config.total_connections(),
136
+ }
137
+ if config.requires_pool()
138
+ else None
139
+ ),
141
140
  )
142
141
 
143
142
  if backend_type == BackendType.DBAPI:
@@ -188,13 +187,11 @@ class BackendSelector:
188
187
 
189
188
  logger.info(
190
189
  "DBAPI configuration validated",
191
- extra={
192
- "hostname": config.iris_hostname,
193
- "port": config.iris_port,
194
- "namespace": config.iris_namespace,
195
- "pool_size": config.pool_size,
196
- "pool_overflow": config.pool_max_overflow,
197
- },
190
+ hostname=config.iris_hostname,
191
+ port=config.iris_port,
192
+ namespace=config.iris_namespace,
193
+ pool_size=config.pool_size,
194
+ pool_overflow=config.pool_max_overflow,
198
195
  )
199
196
 
200
197
  # Embedded backend validation
@@ -227,11 +224,9 @@ class BackendSelector:
227
224
  executor = DBAPIExecutor(config)
228
225
  logger.info(
229
226
  "DBAPI executor created",
230
- extra={
231
- "executor_type": "DBAPIExecutor",
232
- "pool_size": config.pool_size,
233
- "otel_enabled": config.enable_otel,
234
- },
227
+ executor_type="DBAPIExecutor",
228
+ pool_size=config.pool_size,
229
+ otel_enabled=config.enable_otel,
235
230
  )
236
231
  return executor
237
232
 
@@ -274,10 +269,8 @@ class BackendSelector:
274
269
  # backend_type is now set in IRISExecutor.__init__
275
270
  logger.info(
276
271
  "Embedded executor created",
277
- extra={
278
- "executor_type": "IRISExecutor",
279
- "backend_type": executor.backend_type,
280
- },
272
+ executor_type="IRISExecutor",
273
+ backend_type=executor.backend_type,
281
274
  )
282
275
  return executor
283
276
 
@@ -6,11 +6,12 @@ Handles query parsing, array parameter translation, and regclass resolution.
6
6
  """
7
7
 
8
8
  import json
9
- import logging
10
9
  import re
11
10
  from dataclasses import dataclass, field
12
11
  from typing import Any
13
12
 
13
+ import structlog
14
+
14
15
  from iris_pgwire.schema_mapper import IRIS_SCHEMA
15
16
 
16
17
  from .oid_generator import OIDGenerator
@@ -22,7 +23,7 @@ from .pg_index import PgIndexEmulator
22
23
  from .pg_namespace import PgNamespaceEmulator
23
24
  from .pg_type import PgTypeEmulator
24
25
 
25
- logger = logging.getLogger(__name__)
26
+ logger = structlog.get_logger(__name__)
26
27
 
27
28
 
28
29
  @dataclass
@@ -13,11 +13,12 @@ Research: R2 (Queue-based connection pooling)
13
13
  """
14
14
 
15
15
  import asyncio
16
- import logging
17
16
  import time
18
17
  import uuid
19
18
  from datetime import UTC, datetime
20
19
 
20
+ import structlog
21
+
21
22
  from iris_pgwire.models.backend_config import BackendConfig
22
23
  from iris_pgwire.models.connection_pool_state import ConnectionPoolState
23
24
  from iris_pgwire.models.dbapi_connection import (
@@ -25,7 +26,7 @@ from iris_pgwire.models.dbapi_connection import (
25
26
  DBAPIConnection,
26
27
  )
27
28
 
28
- logger = logging.getLogger(__name__)
29
+ logger = structlog.get_logger(__name__)
29
30
 
30
31
 
31
32
  class IRISConnectionPool:
@@ -76,14 +77,11 @@ class IRISConnectionPool:
76
77
  self._last_error: str | None = None
77
78
 
78
79
  logger.info(
79
- "IRIS connection pool initialized",
80
- extra={
81
- "pool_size": config.pool_size,
82
- "max_overflow": config.pool_max_overflow,
83
- "total_capacity": config.total_connections(),
84
- "timeout": config.pool_timeout,
85
- "recycle": config.pool_recycle,
86
- },
80
+ "Connection pool initialized",
81
+ pool_size=config.pool_size,
82
+ max_overflow=config.pool_max_overflow,
83
+ timeout=config.pool_timeout,
84
+ recycle_seconds=config.pool_recycle,
87
85
  )
88
86
 
89
87
  async def acquire(self) -> DBAPIConnection:
@@ -117,13 +115,12 @@ class IRISConnectionPool:
117
115
 
118
116
  # Check if connection needs recycling
119
117
  if conn_wrapper.should_recycle():
120
- logger.info(
121
- "Connection recycling triggered",
122
- extra={
123
- "connection_id": conn_wrapper.connection_id,
124
- "age_seconds": conn_wrapper.age_seconds(),
125
- },
126
- )
118
+ logger.info(
119
+ "Recycling old connection",
120
+ connection_id=conn_wrapper.connection_id,
121
+ age_seconds=round(conn_wrapper.age_seconds, 1),
122
+ )
123
+
127
124
  await self._recycle_connection(conn_wrapper)
128
125
  # Continue loop to get another connection
129
126
  continue
@@ -137,9 +134,13 @@ class IRISConnectionPool:
137
134
  ).total_seconds()
138
135
 
139
136
  if idle_seconds > 10.0:
140
- logger.debug(
141
- f"Connection {conn_wrapper.connection_id} idle for {idle_seconds:.1f}s, checking health"
142
- )
137
+ logger.debug(
138
+ "Acquired connection from pool",
139
+ connection_id=conn_wrapper.connection_id,
140
+ wait_ms=round(wait_ms, 2),
141
+ )
142
+
143
+
143
144
  is_healthy = await self._check_connection_health(conn_wrapper)
144
145
  if not is_healthy:
145
146
  logger.warning(
@@ -187,10 +188,8 @@ class IRISConnectionPool:
187
188
  except (asyncio.TimeoutError, TimeoutError):
188
189
  logger.error(
189
190
  f"Connection acquisition timeout after {self.config.pool_timeout}s",
190
- extra={
191
- "pool_size": len(self._connections),
192
- "in_use": self._connections_in_use(),
193
- },
191
+ pool_size=len(self._connections),
192
+ in_use=self._connections_in_use(),
194
193
  )
195
194
  raise
196
195
  except Exception as e:
@@ -226,7 +225,7 @@ class IRISConnectionPool:
226
225
  if not conn_wrapper.is_healthy:
227
226
  logger.warning(
228
227
  "Unhealthy connection removed from pool",
229
- extra={"connection_id": conn_wrapper.connection_id},
228
+ connection_id=conn_wrapper.connection_id,
230
229
  )
231
230
  await self._remove_connection(conn_wrapper)
232
231
  return
@@ -276,20 +275,18 @@ class IRISConnectionPool:
276
275
 
277
276
  logger.info(
278
277
  "Pool health check",
279
- extra={
280
- "total": total_connections,
281
- "in_use": connections_in_use,
282
- "available": connections_available,
283
- "utilization": state.utilization_percent(),
284
- "is_healthy": self._is_healthy,
285
- },
278
+ total=total_connections,
279
+ in_use=connections_in_use,
280
+ available=connections_available,
281
+ utilization=state.utilization_percent(),
282
+ is_healthy=self._is_healthy,
286
283
  )
287
284
 
288
285
  return state
289
286
 
290
287
  async def close(self) -> None:
291
288
  """Close all connections and shutdown pool."""
292
- logger.info("Closing connection pool", extra={"connections": len(self._connections)})
289
+ logger.info("Closing connection pool", connections=len(self._connections))
293
290
 
294
291
  # Close all connections
295
292
  for conn_id, conn_wrapper in list(self._connections.items()):
@@ -343,13 +340,12 @@ class IRISConnectionPool:
343
340
  self._total_created += 1
344
341
 
345
342
  logger.info(
346
- "Created new connection",
347
- extra={
348
- "connection_id": conn_wrapper.connection_id,
349
- "total_connections": len(self._connections),
350
- },
343
+ "Removing idle overflow connection",
344
+ connection_id=conn_wrapper.connection_id,
345
+ idle_seconds=round(conn_wrapper.idle_seconds, 1),
351
346
  )
352
347
 
348
+
353
349
  return conn_wrapper
354
350
 
355
351
  except Exception as e:
@@ -369,13 +365,12 @@ class IRISConnectionPool:
369
365
  del self._connections[conn_wrapper.connection_id]
370
366
  self._total_recycled += 1
371
367
 
372
- logger.info(
373
- "Connection recycled",
374
- extra={
375
- "connection_id": conn_wrapper.connection_id,
376
- "age_seconds": conn_wrapper.age_seconds(),
377
- },
378
- )
368
+ logger.info(
369
+ "Removed connection from pool",
370
+ connection_id=conn_wrapper.connection_id,
371
+ is_overflow=conn_wrapper.is_overflow,
372
+ )
373
+
379
374
 
380
375
  async def _check_connection_health(self, conn_wrapper: DBAPIConnection) -> bool:
381
376
  """
@@ -448,7 +443,7 @@ class IRISConnectionPool:
448
443
  if elapsed_ms > 1.0:
449
444
  logger.warning(
450
445
  "Slow connection acquisition",
451
- extra={"acquisition_ms": round(elapsed_ms, 3)},
446
+ acquisition_ms=round(elapsed_ms, 3),
452
447
  )
453
448
 
454
449
  @property
@@ -14,11 +14,12 @@ Contract: contracts/dbapi-executor-contract.md
14
14
  """
15
15
 
16
16
  import asyncio
17
- import logging
18
17
  import re
19
18
  import time
20
19
  from typing import Any
21
20
 
21
+ import structlog
22
+
22
23
  from iris_pgwire.catalog import CatalogRouter
23
24
  from iris_pgwire.dbapi_connection_pool import IRISConnectionPool
24
25
  from iris_pgwire.models.backend_config import BackendConfig
@@ -27,7 +28,7 @@ from iris_pgwire.models.vector_query_request import VectorQueryRequest
27
28
  from iris_pgwire.sql_translator import SQLPipeline
28
29
  from iris_pgwire.sql_translator.parser import get_parser
29
30
 
30
- logger = logging.getLogger(__name__)
31
+ logger = structlog.get_logger(__name__)
31
32
 
32
33
 
33
34
  class DBAPIExecutor:
@@ -72,14 +73,12 @@ class DBAPIExecutor:
72
73
 
73
74
  logger.info(
74
75
  "DBAPI executor initialized",
75
- extra={
76
- "backend_type": self.backend_type,
77
- "hostname": config.iris_hostname,
78
- "port": config.iris_port,
79
- "namespace": config.iris_namespace,
80
- "pool_size": config.pool_size,
81
- "strict_single_connection": config.strict_single_connection,
82
- },
76
+ backend_type=self.backend_type,
77
+ hostname=config.iris_hostname,
78
+ port=config.iris_port,
79
+ namespace=config.iris_namespace,
80
+ pool_size=config.pool_size,
81
+ strict_single_connection=config.strict_single_connection,
83
82
  )
84
83
 
85
84
  def _translate_placeholders(self, sql: str) -> str:
@@ -174,11 +173,9 @@ class DBAPIExecutor:
174
173
 
175
174
  logger.debug(
176
175
  "Query executed",
177
- extra={
178
- "sql": sql[:100],
179
- "rows_returned": len(rows),
180
- "elapsed_ms": round(elapsed_ms, 2),
181
- },
176
+ sql=sql[:100],
177
+ rows_returned=len(rows),
178
+ elapsed_ms=round(elapsed_ms, 2),
182
179
  )
183
180
 
184
181
  return {
@@ -207,7 +204,8 @@ class DBAPIExecutor:
207
204
 
208
205
  logger.error(
209
206
  f"Query execution failed: {e}",
210
- extra={"sql": sql[:200], "connection_lost": connection_lost},
207
+ sql=sql[:200],
208
+ connection_lost=connection_lost,
211
209
  )
212
210
  self._total_errors += 1
213
211
 
@@ -266,10 +264,8 @@ class DBAPIExecutor:
266
264
 
267
265
  logger.debug(
268
266
  "Executing executemany()",
269
- extra={
270
- "sql": clean_sql[:100],
271
- "batch_size": len(final_params_list),
272
- },
267
+ sql=clean_sql[:100],
268
+ batch_size=len(final_params_list),
273
269
  )
274
270
 
275
271
  cursor.executemany(clean_sql, final_params_list)
@@ -291,11 +287,9 @@ class DBAPIExecutor:
291
287
 
292
288
  logger.info(
293
289
  "Batch executed successfully",
294
- extra={
295
- "sql": sql[:100],
296
- "rows_affected": rows_affected,
297
- "elapsed_ms": round(elapsed_ms, 2),
298
- },
290
+ sql=sql[:100],
291
+ rows_affected=rows_affected,
292
+ elapsed_ms=round(elapsed_ms, 2),
299
293
  )
300
294
 
301
295
  return {
@@ -325,7 +319,8 @@ class DBAPIExecutor:
325
319
 
326
320
  logger.error(
327
321
  f"Batch execution failed: {e}",
328
- extra={"sql": sql[:200], "connection_lost": connection_lost},
322
+ sql=sql[:200],
323
+ connection_lost=connection_lost,
329
324
  )
330
325
  self._total_errors += 1
331
326
 
@@ -467,33 +462,27 @@ class DBAPIExecutor:
467
462
  if request.exceeds_sla():
468
463
  logger.warning(
469
464
  "Vector translation exceeded 5ms SLA",
470
- extra={
471
- "request_id": request.request_id,
472
- "translation_ms": request.translation_time_ms,
473
- "operator": request.vector_operator,
474
- "dimensions": request.vector_dimensions,
475
- },
465
+ request_id=request.request_id,
466
+ translation_ms=request.translation_time_ms,
467
+ operator=request.vector_operator,
468
+ dimensions=request.vector_dimensions,
476
469
  )
477
470
 
478
471
  # Execute translated SQL
479
472
  logger.info(
480
473
  "Executing vector query",
481
- extra={
482
- "request_id": request.request_id,
483
- "operator": request.vector_operator,
484
- "dimensions": request.vector_dimensions,
485
- "translation_ms": request.translation_time_ms,
486
- },
474
+ request_id=request.request_id,
475
+ operator=request.vector_operator,
476
+ dimensions=request.vector_dimensions,
477
+ translation_ms=request.translation_time_ms,
487
478
  )
488
479
 
489
480
  results = await self.execute_query(request.translated_sql)
490
481
 
491
482
  logger.debug(
492
483
  "Vector query completed",
493
- extra={
494
- "request_id": request.request_id,
495
- "rows_returned": len(results.get("rows", [])),
496
- },
484
+ request_id=request.request_id,
485
+ rows_returned=len(results.get("rows", [])),
497
486
  )
498
487
 
499
488
  return results
@@ -559,10 +548,8 @@ class DBAPIExecutor:
559
548
  """
560
549
  logger.info(
561
550
  "Closing DBAPI executor",
562
- extra={
563
- "total_queries": self._total_queries,
564
- "total_errors": self._total_errors,
565
- },
551
+ total_queries=self._total_queries,
552
+ total_errors=self._total_errors,
566
553
  )
567
554
 
568
555
  # Close connection pool
@@ -7,7 +7,7 @@ Provides translation, cache management, and diagnostic interfaces.
7
7
  Constitutional Compliance: High-performance API with sub-5ms response times.
8
8
  """
9
9
 
10
- import logging
10
+ import structlog
11
11
  from dataclasses import asdict
12
12
  from datetime import UTC, datetime
13
13
  from typing import Any
@@ -134,7 +134,7 @@ class SQLTranslationAPI:
134
134
  translator: SQL translator instance (uses global if None)
135
135
  """
136
136
  self.translator = translator or get_translator()
137
- self.logger = logging.getLogger("iris_pgwire.sql_translator.api")
137
+ self.logger = structlog.get_logger("iris_pgwire.sql_translator.api")
138
138
 
139
139
  # Request tracking
140
140
  self._request_count = 0
@@ -8,13 +8,14 @@ Constitutional Compliance: Complete transparency in translation decisions.
8
8
  """
9
9
 
10
10
  import json
11
- import logging
12
11
  import threading
13
12
  from dataclasses import asdict, dataclass
14
13
  from datetime import UTC, datetime
15
14
  from enum import Enum
16
15
  from typing import Any
17
16
 
17
+ import structlog
18
+
18
19
  from .models import DebugTrace
19
20
 
20
21
 
@@ -71,14 +72,7 @@ class DebugTracer:
71
72
 
72
73
  def _setup_logging(self):
73
74
  """Setup structured logging for debug output"""
74
- self.logger = logging.getLogger("iris_pgwire.sql_translator.debug")
75
-
76
- if not self.logger.handlers:
77
- handler = logging.StreamHandler()
78
- formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
79
- handler.setFormatter(formatter)
80
- self.logger.addHandler(handler)
81
- self.logger.setLevel(logging.DEBUG)
75
+ self.logger = structlog.get_logger("iris_pgwire.sql_translator.debug")
82
76
 
83
77
  def start_trace(self, trace_id: str, original_sql: str) -> DebugTrace:
84
78
  """
@@ -463,7 +457,7 @@ class DebugTracer:
463
457
  html_parts.append("<h2>Parsing Steps</h2>")
464
458
  for i, step in enumerate(trace.parsing_steps):
465
459
  html_parts.append("<div class='step'>")
466
- html_parts.append(f"<h3>Step {i+1}: {step.step_name}</h3>")
460
+ html_parts.append(f"<h3>Step {i + 1}: {step.step_name}</h3>")
467
461
  html_parts.append(f"<p><strong>Duration:</strong> {step.duration_ms}ms</p>")
468
462
  html_parts.append(f"<p><strong>Input:</strong></p><pre>{step.input_sql}</pre>")
469
463
  html_parts.append(
@@ -481,7 +475,7 @@ class DebugTracer:
481
475
  for i, decision in enumerate(trace.mapping_decisions):
482
476
  css_class = "warning" if decision.confidence < 0.7 else "step"
483
477
  html_parts.append(f"<div class='{css_class}'>")
484
- html_parts.append(f"<h3>Decision {i+1}: {decision.construct}</h3>")
478
+ html_parts.append(f"<h3>Decision {i + 1}: {decision.construct}</h3>")
485
479
  html_parts.append(
486
480
  f"<p><strong>Chosen Mapping:</strong> {decision.chosen_mapping}</p>"
487
481
  )
@@ -501,7 +495,7 @@ class DebugTracer:
501
495
  html_parts.append("<h2>Warnings</h2>")
502
496
  for i, warning in enumerate(trace.warnings):
503
497
  html_parts.append("<div class='warning'>")
504
- html_parts.append(f"<h3>Warning {i+1}</h3>")
498
+ html_parts.append(f"<h3>Warning {i + 1}</h3>")
505
499
  html_parts.append(f"<p>{warning}</p>")
506
500
  html_parts.append("</div>")
507
501
 
@@ -570,9 +564,9 @@ class DebugTracer:
570
564
 
571
565
  self._events.append(event)
572
566
 
573
- # Log to standard logger
574
- log_level = getattr(logging, level.value)
575
- self.logger.log(log_level, f"[{component}] {message}", extra={"data": data})
567
+ # Log to structured logger
568
+ log_method = getattr(self.logger, level.value.lower())
569
+ log_method(f"[{component}] {message}", **data)
576
570
 
577
571
 
578
572
  # Global tracer instance
@@ -12,8 +12,14 @@ Constitutional Requirements:
12
12
 
13
13
  import re
14
14
 
15
+ import structlog
16
+
15
17
  from iris_pgwire.schema_mapper import IRIS_SCHEMA
16
18
 
19
+ from .logging_config import DDL_SKIP_FORMAT
20
+
21
+ logger = structlog.get_logger(__name__)
22
+
17
23
 
18
24
  class IdentifierNormalizer:
19
25
  """
@@ -174,11 +180,6 @@ class IdentifierNormalizer:
174
180
  flags=re.DOTALL,
175
181
  )
176
182
  # Log warning
177
- import logging
178
-
179
- from .logging_config import DDL_SKIP_FORMAT
180
-
181
- logger = logging.getLogger("iris_pgwire.sql_translator.normalizer")
182
183
  logger.warning(DDL_SKIP_FORMAT.format("GENERATED column"))
183
184
 
184
185
  # CRITICAL FIX: Exclude string literals from normalization
@@ -216,11 +217,6 @@ class IdentifierNormalizer:
216
217
  if "USING" in normalized_sql.upper():
217
218
  normalized_sql = re.sub(r"(?i)\s+USING\s+btree\b", "", normalized_sql)
218
219
  # Log warning
219
- import logging
220
-
221
- from .logging_config import DDL_SKIP_FORMAT
222
-
223
- logger = logging.getLogger("iris_pgwire.sql_translator.normalizer")
224
220
  logger.warning(DDL_SKIP_FORMAT.format("USING btree"))
225
221
 
226
222
  if "WITH" in normalized_sql.upper() and "FILLFACTOR" in normalized_sql.upper():
@@ -228,11 +224,6 @@ class IdentifierNormalizer:
228
224
  r"(?i)\s+WITH\s*\(\s*fillfactor\s*=\s*\d+\s*\)", "", normalized_sql
229
225
  )
230
226
  # Log warning
231
- import logging
232
-
233
- from .logging_config import DDL_SKIP_FORMAT
234
-
235
- logger = logging.getLogger("iris_pgwire.sql_translator.normalizer")
236
227
  logger.warning(DDL_SKIP_FORMAT.format("WITH (fillfactor)"))
237
228
 
238
229
  if "::" in normalized_sql:
@@ -243,11 +234,6 @@ class IdentifierNormalizer:
243
234
  normalized_sql,
244
235
  )
245
236
  # Log warning
246
- import logging
247
-
248
- from .logging_config import DDL_SKIP_FORMAT
249
-
250
- logger = logging.getLogger("iris_pgwire.sql_translator.normalizer")
251
237
  logger.warning(DDL_SKIP_FORMAT.format("Cast syntax"))
252
238
 
253
239
  return normalized_sql, identifier_count
@@ -4,12 +4,13 @@ SQL Interceptor - Registry for stubbed PostgreSQL system responses (Feature 036)
4
4
  This module decouples the procedural interception logic from IRISExecutor.
5
5
  """
6
6
 
7
- import logging
8
7
  import re
9
8
  from dataclasses import dataclass
10
9
  from typing import Any, Callable, Dict, List, Optional
11
10
 
12
- logger = logging.getLogger("iris_pgwire.sql_translator.interceptor")
11
+ import structlog
12
+
13
+ logger = structlog.get_logger("iris_pgwire.sql_translator.interceptor")
13
14
 
14
15
 
15
16
  @dataclass
@@ -10,7 +10,7 @@ This orchestrates the various stages of SQL translation:
10
10
  6. Normalization (Identifiers, dates, booleans, enums)
11
11
  """
12
12
 
13
- import logging
13
+ import structlog
14
14
  from dataclasses import dataclass
15
15
  from typing import Any
16
16
 
@@ -18,7 +18,7 @@ from .models import PerformanceStats, TranslationResult
18
18
  from .normalizer import SQLTranslator
19
19
  from .refiner import SQLRefiner
20
20
 
21
- logger = logging.getLogger("iris_pgwire.sql_translator.pipeline")
21
+ logger = structlog.get_logger("iris_pgwire.sql_translator.pipeline")
22
22
 
23
23
 
24
24
  class SQLPipeline:
@@ -6,10 +6,11 @@ but are required for specific ORMs or IRIS SQL compiler quirks.
6
6
  """
7
7
 
8
8
  import re
9
- import logging
10
9
  from dataclasses import dataclass
11
10
 
12
- logger = logging.getLogger("iris_pgwire.sql_translator.refiner")
11
+ import structlog
12
+
13
+ logger = structlog.get_logger("iris_pgwire.sql_translator.refiner")
13
14
 
14
15
 
15
16
  @dataclass
@@ -7,7 +7,6 @@ Coordinates all translation components with constitutional compliance monitoring
7
7
  Constitutional Compliance: Sub-5ms translation with high-confidence mappings.
8
8
  """
9
9
 
10
- import logging
11
10
  import threading
12
11
  import uuid
13
12
  from concurrent.futures import ThreadPoolExecutor
@@ -136,9 +135,6 @@ class IRISSQLTranslator:
136
135
  self._total_translations = 0
137
136
  self._start_time = datetime.now(UTC)
138
137
 
139
- # Setup logging
140
- self.logger = logging.getLogger("iris_pgwire.sql_translator")
141
-
142
138
  # Performance optimization
143
139
  self._thread_pool = ThreadPoolExecutor(max_workers=4, thread_name_prefix="iris_translator")
144
140
 
@@ -7,12 +7,13 @@ to the original IRIS SQL, ensuring constitutional compliance with accuracy requi
7
7
  Constitutional Compliance: High-confidence validation ensuring accurate translation.
8
8
  """
9
9
 
10
- import logging
11
10
  import re
12
11
  from dataclasses import dataclass, field
13
12
  from enum import Enum
14
13
  from typing import Any
15
14
 
15
+ import structlog
16
+
16
17
  from .models import (
17
18
  ConstructMapping,
18
19
  IssueSeverity,
@@ -79,7 +80,7 @@ class SemanticValidator:
79
80
  validation_level: Level of validation rigor to apply
80
81
  """
81
82
  self.validation_level = validation_level
82
- self.logger = logging.getLogger("iris_pgwire.sql_translator.validator")
83
+ self.logger = structlog.get_logger("iris_pgwire.sql_translator.validator")
83
84
 
84
85
  # Validation rules and patterns
85
86
  self._setup_validation_rules()
@@ -7,16 +7,17 @@ must be literals, not parameters.
7
7
  """
8
8
 
9
9
  import base64
10
- import logging
11
10
  import re
12
11
  import struct
13
12
  import time
14
13
  from dataclasses import dataclass, field
15
14
  from typing import Any
16
15
 
16
+ import structlog
17
+
17
18
  # Feature 021: PostgreSQL→IRIS SQL normalization
18
19
 
19
- logger = logging.getLogger(__name__)
20
+ logger = structlog.get_logger(__name__)
20
21
 
21
22
 
22
23
  @dataclass
File without changes
File without changes
File without changes
File without changes