iris-pgwire 1.5.7__tar.gz → 1.5.9__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 (121) hide show
  1. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/.gitignore +32 -0
  2. iris_pgwire-1.5.9/PKG-INFO +298 -0
  3. iris_pgwire-1.5.9/README.md +212 -0
  4. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/pyproject.toml +3 -0
  5. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/__init__.py +1 -1
  6. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/dbapi_executor.py +46 -8
  7. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/integratedml.py +1 -1
  8. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/protocol.py +29 -8
  9. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/code_quality_validator.py +12 -7
  10. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/package_metadata_validator.py +8 -4
  11. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/security_validator.py +11 -8
  12. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/boolean_translator.py +16 -16
  13. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/identifier_normalizer.py +1 -2
  14. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/normalizer.py +21 -0
  15. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/vector_optimizer.py +193 -1
  16. iris_pgwire-1.5.7/PKG-INFO +0 -372
  17. iris_pgwire-1.5.7/README.md +0 -288
  18. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/LICENSE +0 -0
  19. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/_column_naming.py +0 -0
  20. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/_noop_cursor.py +0 -0
  21. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/_result_processing.py +0 -0
  22. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/_type_mapping.py +0 -0
  23. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/__init__.py +0 -0
  24. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/auth_selector.py +0 -0
  25. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/gssapi_auth.py +0 -0
  26. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/oauth_bridge.py +0 -0
  27. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/scram.py +0 -0
  28. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/auth/wallet_credentials.py +0 -0
  29. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/backend_selector.py +0 -0
  30. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/bulk_executor.py +0 -0
  31. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/__init__.py +0 -0
  32. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/catalog_functions.py +0 -0
  33. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/catalog_router.py +0 -0
  34. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/oid_generator.py +0 -0
  35. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_attrdef.py +0 -0
  36. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_attribute.py +0 -0
  37. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_class.py +0 -0
  38. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_constraint.py +0 -0
  39. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_index.py +0 -0
  40. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_namespace.py +0 -0
  41. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/catalog/pg_type.py +0 -0
  42. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/column_validator.py +0 -0
  43. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/config.py +0 -0
  44. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/config_schema.py +0 -0
  45. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/constitutional.py +0 -0
  46. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/__init__.py +0 -0
  47. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/bulk_insert.py +0 -0
  48. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/date_horolog.py +0 -0
  49. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/ddl_idempotency.py +0 -0
  50. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/ddl_splitter.py +0 -0
  51. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/json_path.py +0 -0
  52. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/conversions/vector_syntax.py +0 -0
  53. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/copy_handler.py +0 -0
  54. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/csv_processor.py +0 -0
  55. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/dbapi_connection_pool.py +0 -0
  56. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/debug_tracer.py +0 -0
  57. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/health_checker.py +0 -0
  58. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/iris_constructs.py +0 -0
  59. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/iris_executor.py +0 -0
  60. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/iris_log_handler.py +0 -0
  61. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/iris_user_management.py +0 -0
  62. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/migrations/__init__.py +0 -0
  63. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/migrations/__main__.py +0 -0
  64. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/migrations/executor.py +0 -0
  65. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/__init__.py +0 -0
  66. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/backend_config.py +0 -0
  67. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/connection_pool_state.py +0 -0
  68. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/dbapi_connection.py +0 -0
  69. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/ipm_metadata.py +0 -0
  70. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/models/vector_query_request.py +1 -1
  71. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/observability.py +0 -0
  72. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/performance_monitor.py +0 -0
  73. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/__init__.py +0 -0
  74. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/__main__.py +0 -0
  75. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/documentation_validator.py +0 -0
  76. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/quality/validator.py +0 -0
  77. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/schema_mapper.py +0 -0
  78. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/server.py +0 -0
  79. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/__init__.py +0 -0
  80. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/alias_extractor.py +0 -0
  81. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/api.py +0 -0
  82. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/cache.py +0 -0
  83. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/confidence_analyzer.py +0 -0
  84. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/config.py +0 -0
  85. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/constraint_translator.py +0 -0
  86. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/copy_parser.py +0 -0
  87. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/date_translator.py +0 -0
  88. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/ddl_parser.py +0 -0
  89. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/ddl_translator.py +0 -0
  90. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/debug.py +0 -0
  91. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/default_values.py +0 -0
  92. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/enum_registry.py +0 -0
  93. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/enum_translator.py +0 -0
  94. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/error_handler.py +0 -0
  95. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/index_validator.py +0 -0
  96. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/interceptor.py +0 -0
  97. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/logging_config.py +0 -0
  98. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/mappings/__init__.py +0 -0
  99. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/mappings/constructs.py +0 -0
  100. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/mappings/datatypes.py +0 -0
  101. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/mappings/document_filters.py +0 -0
  102. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/mappings/functions.py +0 -0
  103. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/metadata_cache.py +0 -0
  104. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/metrics.py +0 -0
  105. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/models.py +0 -0
  106. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/parser.py +0 -0
  107. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/performance_monitor.py +0 -0
  108. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/pipeline.py +0 -0
  109. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/refiner.py +0 -0
  110. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/reserved_words.py +0 -0
  111. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/returning_plan.py +0 -0
  112. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/skipped_table_set.py +0 -0
  113. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/statement_filter.py +0 -0
  114. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/transaction_translator.py +0 -0
  115. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/translator.py +0 -0
  116. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/type_translator.py +0 -0
  117. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/sql_translator/validator.py +0 -0
  118. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/testing/__init__.py +0 -0
  119. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/testing/base_fixture_builder.py +0 -0
  120. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/type_mapping.py +0 -0
  121. {iris_pgwire-1.5.7 → iris_pgwire-1.5.9}/src/iris_pgwire/vector_metrics.py +0 -0
@@ -79,3 +79,35 @@ docs/articles/developer-community-article.md
79
79
  docs/presentations/
80
80
  docs/articles/
81
81
  /.opencode
82
+
83
+ # Build / coverage artifacts
84
+ coverage.json
85
+ coverage.xml
86
+ interrogate_badge.svg
87
+ test_failures.jsonl
88
+ htmlcov/
89
+ pgwire.log
90
+ server_log.txt
91
+
92
+ # Docker runtime files (not for source control)
93
+ merge.cpf
94
+ iris_pgwire.json
95
+
96
+ # AI tooling files (not for public repo)
97
+ AGENTS.md
98
+ CODEX.md
99
+ TABNINE.md
100
+
101
+ # Root-level debug/scratch scripts (use scripts/ directory instead)
102
+ check_intersystems.py
103
+ check_iris.py
104
+ check_resolve.py
105
+ find_shadowing.py
106
+ inspect_monkeypatch.py
107
+ repro_scoping.py
108
+ test_conn.py
109
+ test_connection_stability.py
110
+ test_pg_type.py
111
+ test_scope.py
112
+ update_article.py
113
+ verify_demo.sql
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.4
2
+ Name: iris-pgwire
3
+ Version: 1.5.9
4
+ Summary: PostgreSQL Wire Protocol Server for InterSystems IRIS - Connect BI tools, Python frameworks, and PostgreSQL clients to IRIS databases
5
+ Project-URL: Homepage, https://github.com/intersystems-community/iris-pgwire
6
+ Project-URL: Documentation, https://github.com/intersystems-community/iris-pgwire#readme
7
+ Project-URL: Repository, https://github.com/intersystems-community/iris-pgwire
8
+ Project-URL: Issues, https://github.com/intersystems-community/iris-pgwire/issues
9
+ Project-URL: Changelog, https://github.com/intersystems-community/iris-pgwire/releases
10
+ Author-email: Thomas Dyar <thomas.dyar@intersystems.com>
11
+ Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
12
+ License: MIT License
13
+
14
+ Copyright (c) 2025 Thomas Dyar <thomas.dyar@intersystems.com>
15
+
16
+ Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ of this software and associated documentation files (the "Software"), to deal
18
+ in the Software without restriction, including without limitation the rights
19
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ copies of the Software, and to permit persons to whom the Software is
21
+ furnished to do so, subject to the following conditions:
22
+
23
+ The above copyright notice and this permission notice shall be included in all
24
+ copies or substantial portions of the Software.
25
+
26
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32
+ SOFTWARE.
33
+ License-File: LICENSE
34
+ Keywords: async,bi-tools,database,fastapi,intersystems,iris,llm,pgvector,postgres,postgresql,rag,sql,sqlalchemy,vector-database,wire-protocol
35
+ Classifier: Development Status :: 5 - Production/Stable
36
+ Classifier: Framework :: AsyncIO
37
+ Classifier: Framework :: FastAPI
38
+ Classifier: Intended Audience :: Developers
39
+ Classifier: Intended Audience :: System Administrators
40
+ Classifier: License :: OSI Approved :: MIT License
41
+ Classifier: Operating System :: OS Independent
42
+ Classifier: Programming Language :: Python :: 3
43
+ Classifier: Programming Language :: Python :: 3 :: Only
44
+ Classifier: Programming Language :: Python :: 3.11
45
+ Classifier: Programming Language :: Python :: 3.12
46
+ Classifier: Topic :: Database
47
+ Classifier: Topic :: Database :: Database Engines/Servers
48
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
49
+ Classifier: Topic :: System :: Networking
50
+ Classifier: Typing :: Typed
51
+ Requires-Python: >=3.11
52
+ Requires-Dist: cryptography>=41.0.0
53
+ Requires-Dist: intersystems-irispython>=5.1.2
54
+ Requires-Dist: opentelemetry-api>=1.20.0
55
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0
56
+ Requires-Dist: opentelemetry-instrumentation-asyncio>=0.41b0
57
+ Requires-Dist: opentelemetry-sdk>=1.20.0
58
+ Requires-Dist: prometheus-client>=0.17.0
59
+ Requires-Dist: psycopg2-binary>=2.9.10
60
+ Requires-Dist: pydantic>=2.0.0
61
+ Requires-Dist: pyyaml>=6.0.0
62
+ Requires-Dist: sqlparse>=0.4.0
63
+ Requires-Dist: structlog>=23.0.0
64
+ Provides-Extra: ai
65
+ Requires-Dist: iris-agentic-dev>=1.0; extra == 'ai'
66
+ Provides-Extra: dev
67
+ Requires-Dist: black>=23.0.0; extra == 'dev'
68
+ Requires-Dist: mypy>=1.5.0; extra == 'dev'
69
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
70
+ Provides-Extra: iris
71
+ Provides-Extra: kerberos
72
+ Requires-Dist: gssapi>=1.8.0; extra == 'kerberos'
73
+ Provides-Extra: test
74
+ Requires-Dist: docker>=6.0.0; extra == 'test'
75
+ Requires-Dist: iris-devtester>=0.1.0; extra == 'test'
76
+ Requires-Dist: k5test>=0.10.3; extra == 'test'
77
+ Requires-Dist: psycopg[binary]>=3.1.0; extra == 'test'
78
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
79
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
80
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
81
+ Requires-Dist: pytest-fixtures>=3.0.0; extra == 'test'
82
+ Requires-Dist: pytest-timeout>=2.2.0; extra == 'test'
83
+ Requires-Dist: pytest>=7.0.0; extra == 'test'
84
+ Requires-Dist: sqlparse>=0.4.0; extra == 'test'
85
+ Description-Content-Type: text/markdown
86
+
87
+ # iris-pgwire
88
+
89
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
90
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
91
+ [![Coverage: 92%](https://img.shields.io/badge/coverage-92%25-brightgreen.svg)](https://github.com/intersystems-community/iris-pgwire)
92
+
93
+ PostgreSQL wire protocol server for InterSystems IRIS. Connects BI tools, Python frameworks, data pipelines, and any PostgreSQL-compatible client to IRIS databases — no IRIS-specific drivers needed.
94
+
95
+ **Connection string**: `postgresql://user:pass@localhost:5432/USER`
96
+
97
+ ---
98
+
99
+ ## Quick Start
100
+
101
+ ### Docker (recommended)
102
+
103
+ ```bash
104
+ git clone https://github.com/intersystems-community/iris-pgwire.git
105
+ cd iris-pgwire
106
+ docker compose up -d
107
+
108
+ # Test it (PGWire runs on port 5432 inside the IRIS container)
109
+ psql -h localhost -p 5432 -U _SYSTEM -d USER -c "SELECT 'Hello from IRIS!'"
110
+ ```
111
+
112
+ ### Python package
113
+
114
+ ```bash
115
+ pip install iris-pgwire psycopg[binary]
116
+
117
+ export IRIS_HOST=localhost IRIS_PORT=1972 \
118
+ IRIS_USERNAME=_SYSTEM IRIS_PASSWORD=SYS IRIS_NAMESPACE=USER
119
+
120
+ python -m iris_pgwire.server
121
+ ```
122
+
123
+ ### First query
124
+
125
+ ```python
126
+ import psycopg
127
+
128
+ with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
129
+ with conn.cursor() as cur:
130
+ cur.execute("SELECT COUNT(*) FROM MyTable")
131
+ print(cur.fetchone()[0])
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Verified Client Compatibility
137
+
138
+ Tested against real IRIS instances via the wire protocol:
139
+
140
+ | Language | Clients |
141
+ | -------- | -------------------------------------------- |
142
+ | Python | psycopg3, asyncpg, SQLAlchemy (sync + async) |
143
+ | Node.js | pg (node-postgres) |
144
+ | Java | PostgreSQL JDBC |
145
+ | .NET | Npgsql |
146
+ | Go | pgx v5 |
147
+ | Ruby | pg gem |
148
+ | Rust | tokio-postgres |
149
+ | PHP | PDO PostgreSQL |
150
+
151
+ **ORMs**: SQLAlchemy, Prisma, Drizzle, Sequelize, Hibernate
152
+ **BI tools**: Apache Superset, Metabase, Grafana (standard PostgreSQL driver)
153
+
154
+ See [Client Compatibility Guide](docs/CLIENT_RECOMMENDATIONS.md) for setup examples.
155
+
156
+ ---
157
+
158
+ ## Key Features
159
+
160
+ **pgvector operators** — `<=>` (cosine), `<#>` (dot product), `<->` (L2) auto-translate to IRIS `VECTOR_COSINE`/`VECTOR_DOT_PRODUCT`. HNSW indexes give 5× speedup at 100K+ vectors. See [Vector Operations](docs/VECTOR_PARAMETER_BINDING.md).
161
+
162
+ **DDL compatibility** — Automatic `public` ↔ `SQLUser` schema mapping; strips `fillfactor`, `GENERATED` columns, `USING btree`, `IF NOT EXISTS` guards, and other PostgreSQL-specific DDL so ORM migrations run cleanly. See [DDL Compatibility](docs/DDL_COMPATIBILITY.md).
163
+
164
+ **SQL translation** — `RETURNING` emulation, `ON CONFLICT`, boolean literals, `pg_catalog` → `INFORMATION_SCHEMA` rewrites, JSON operators (`->` / `->>` → `JSON_EXTRACT`), parameterized queries.
165
+
166
+ **Authentication** — SCRAM-SHA-256, OAuth 2.0 (RFC 6749), IRIS Wallet credentials.
167
+
168
+ **Dual backend** — Embedded Python (irispython, lowest latency) or external DBAPI (standard TCP connection). Selectable via `IRIS_BACKEND` env var.
169
+
170
+ **COPY protocol** — Bulk load via `COPY … FROM STDIN` (~600 rows/sec on DBAPI path).
171
+
172
+ ---
173
+
174
+ ## Usage Examples
175
+
176
+ ### Parameterized queries (psycopg3)
177
+
178
+ ```python
179
+ import psycopg
180
+
181
+ with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
182
+ with conn.cursor() as cur:
183
+ cur.execute("SELECT * FROM MyTable WHERE id = %s", (42,))
184
+ row = cur.fetchone()
185
+ ```
186
+
187
+ ### Vector similarity search
188
+
189
+ ```python
190
+ query_vector = [0.1, 0.2, 0.3]
191
+ with conn.cursor() as cur:
192
+ cur.execute("""
193
+ SELECT id, embedding <=> %s::vector AS score
194
+ FROM vectors
195
+ ORDER BY score
196
+ LIMIT 5
197
+ """, (query_vector,))
198
+ results = cur.fetchall()
199
+ ```
200
+
201
+ ### Async SQLAlchemy
202
+
203
+ ```python
204
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
205
+ from sqlalchemy import text
206
+
207
+ engine = create_async_engine("postgresql+psycopg://localhost:5432/USER")
208
+ SessionLocal = async_sessionmaker(engine, class_=AsyncSession)
209
+
210
+ async def query():
211
+ async with SessionLocal() as session:
212
+ result = await session.execute(text("SELECT * FROM MyTable"))
213
+ return result.fetchall()
214
+ ```
215
+
216
+ ### COPY bulk load
217
+
218
+ ```python
219
+ with conn.cursor() as cur:
220
+ with cur.copy("COPY MyTable (col1, col2) FROM STDIN") as copy:
221
+ for row in data:
222
+ copy.write_row(row)
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Documentation
228
+
229
+ | Guide | Description |
230
+ | ------------------------------------------------------ | ------------------------------------------ |
231
+ | [Installation](docs/INSTALLATION.md) | Docker, PyPI, Embedded Python deployment |
232
+ | [Architecture](docs/ARCHITECTURE.md) | System design, dual backend, request flow |
233
+ | [DDL Compatibility](docs/DDL_COMPATIBILITY.md) | PostgreSQL DDL transformations |
234
+ | [Vector Operations](docs/VECTOR_PARAMETER_BINDING.md) | pgvector syntax, HNSW indexes |
235
+ | [Client Compatibility](docs/CLIENT_RECOMMENDATIONS.md) | Per-language setup and caveats |
236
+ | [Deployment](docs/DEPLOYMENT.md) | Production setup, SSL/TLS, auth |
237
+ | [Performance](docs/PERFORMANCE.md) | Benchmarks, tuning |
238
+ | [Developer Guide](docs/developer_guide.md) | Development setup, contribution guidelines |
239
+
240
+ ---
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ # Install dependencies
246
+ uv sync --frozen
247
+
248
+ # Run unit + contract tests (no IRIS needed)
249
+ pytest tests/unit/ tests/contract/ -v
250
+
251
+ # Run with live IRIS (container must be up)
252
+ docker compose up -d
253
+ PGWIRE_BACKEND_TYPE=dbapi PGWIRE_POOL_SIZE=1 pytest tests/ -v
254
+
255
+ # Code quality check
256
+ python -m iris_pgwire.quality
257
+ ```
258
+
259
+ **Test coverage**: 92% (5349 tests)
260
+ **Code quality**: black (formatter), ruff (linter), bandit (security)
261
+
262
+ ---
263
+
264
+ ## Known Limitations
265
+
266
+ See [KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md) for the full list. Key items:
267
+
268
+ - IRIS Community Edition: 5-user connection limit — use `PGWIRE_POOL_SIZE=1` for dev
269
+ - No native SSL termination — use nginx/HAProxy in front for TLS
270
+ - Kerberos/GSSAPI auth wiring deferred (OAuth 2.0 is the recommended enterprise auth)
271
+ - `INFORMATION_SCHEMA` only, no `pg_catalog` tables (translated automatically)
272
+
273
+ ---
274
+
275
+ ## Contributing
276
+
277
+ ```bash
278
+ git clone https://github.com/intersystems-community/iris-pgwire.git
279
+ cd iris-pgwire
280
+ uv sync --frozen
281
+ docker compose up -d
282
+ pytest tests/unit/ tests/contract/ -v
283
+ ```
284
+
285
+ Open an issue or PR on [GitHub](https://github.com/intersystems-community/iris-pgwire/issues).
286
+
287
+ ---
288
+
289
+ ## Links
290
+
291
+ - [InterSystems IRIS](https://www.intersystems.com/products/intersystems-iris/)
292
+ - [IRIS Documentation](https://docs.intersystems.com/iris/)
293
+ - [PostgreSQL Protocol Spec](https://www.postgresql.org/docs/current/protocol.html)
294
+ - [pgvector](https://github.com/pgvector/pgvector)
295
+
296
+ ---
297
+
298
+ MIT License — see [LICENSE](LICENSE)
@@ -0,0 +1,212 @@
1
+ # iris-pgwire
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
5
+ [![Coverage: 92%](https://img.shields.io/badge/coverage-92%25-brightgreen.svg)](https://github.com/intersystems-community/iris-pgwire)
6
+
7
+ PostgreSQL wire protocol server for InterSystems IRIS. Connects BI tools, Python frameworks, data pipelines, and any PostgreSQL-compatible client to IRIS databases — no IRIS-specific drivers needed.
8
+
9
+ **Connection string**: `postgresql://user:pass@localhost:5432/USER`
10
+
11
+ ---
12
+
13
+ ## Quick Start
14
+
15
+ ### Docker (recommended)
16
+
17
+ ```bash
18
+ git clone https://github.com/intersystems-community/iris-pgwire.git
19
+ cd iris-pgwire
20
+ docker compose up -d
21
+
22
+ # Test it (PGWire runs on port 5432 inside the IRIS container)
23
+ psql -h localhost -p 5432 -U _SYSTEM -d USER -c "SELECT 'Hello from IRIS!'"
24
+ ```
25
+
26
+ ### Python package
27
+
28
+ ```bash
29
+ pip install iris-pgwire psycopg[binary]
30
+
31
+ export IRIS_HOST=localhost IRIS_PORT=1972 \
32
+ IRIS_USERNAME=_SYSTEM IRIS_PASSWORD=SYS IRIS_NAMESPACE=USER
33
+
34
+ python -m iris_pgwire.server
35
+ ```
36
+
37
+ ### First query
38
+
39
+ ```python
40
+ import psycopg
41
+
42
+ with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
43
+ with conn.cursor() as cur:
44
+ cur.execute("SELECT COUNT(*) FROM MyTable")
45
+ print(cur.fetchone()[0])
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Verified Client Compatibility
51
+
52
+ Tested against real IRIS instances via the wire protocol:
53
+
54
+ | Language | Clients |
55
+ | -------- | -------------------------------------------- |
56
+ | Python | psycopg3, asyncpg, SQLAlchemy (sync + async) |
57
+ | Node.js | pg (node-postgres) |
58
+ | Java | PostgreSQL JDBC |
59
+ | .NET | Npgsql |
60
+ | Go | pgx v5 |
61
+ | Ruby | pg gem |
62
+ | Rust | tokio-postgres |
63
+ | PHP | PDO PostgreSQL |
64
+
65
+ **ORMs**: SQLAlchemy, Prisma, Drizzle, Sequelize, Hibernate
66
+ **BI tools**: Apache Superset, Metabase, Grafana (standard PostgreSQL driver)
67
+
68
+ See [Client Compatibility Guide](docs/CLIENT_RECOMMENDATIONS.md) for setup examples.
69
+
70
+ ---
71
+
72
+ ## Key Features
73
+
74
+ **pgvector operators** — `<=>` (cosine), `<#>` (dot product), `<->` (L2) auto-translate to IRIS `VECTOR_COSINE`/`VECTOR_DOT_PRODUCT`. HNSW indexes give 5× speedup at 100K+ vectors. See [Vector Operations](docs/VECTOR_PARAMETER_BINDING.md).
75
+
76
+ **DDL compatibility** — Automatic `public` ↔ `SQLUser` schema mapping; strips `fillfactor`, `GENERATED` columns, `USING btree`, `IF NOT EXISTS` guards, and other PostgreSQL-specific DDL so ORM migrations run cleanly. See [DDL Compatibility](docs/DDL_COMPATIBILITY.md).
77
+
78
+ **SQL translation** — `RETURNING` emulation, `ON CONFLICT`, boolean literals, `pg_catalog` → `INFORMATION_SCHEMA` rewrites, JSON operators (`->` / `->>` → `JSON_EXTRACT`), parameterized queries.
79
+
80
+ **Authentication** — SCRAM-SHA-256, OAuth 2.0 (RFC 6749), IRIS Wallet credentials.
81
+
82
+ **Dual backend** — Embedded Python (irispython, lowest latency) or external DBAPI (standard TCP connection). Selectable via `IRIS_BACKEND` env var.
83
+
84
+ **COPY protocol** — Bulk load via `COPY … FROM STDIN` (~600 rows/sec on DBAPI path).
85
+
86
+ ---
87
+
88
+ ## Usage Examples
89
+
90
+ ### Parameterized queries (psycopg3)
91
+
92
+ ```python
93
+ import psycopg
94
+
95
+ with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
96
+ with conn.cursor() as cur:
97
+ cur.execute("SELECT * FROM MyTable WHERE id = %s", (42,))
98
+ row = cur.fetchone()
99
+ ```
100
+
101
+ ### Vector similarity search
102
+
103
+ ```python
104
+ query_vector = [0.1, 0.2, 0.3]
105
+ with conn.cursor() as cur:
106
+ cur.execute("""
107
+ SELECT id, embedding <=> %s::vector AS score
108
+ FROM vectors
109
+ ORDER BY score
110
+ LIMIT 5
111
+ """, (query_vector,))
112
+ results = cur.fetchall()
113
+ ```
114
+
115
+ ### Async SQLAlchemy
116
+
117
+ ```python
118
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
119
+ from sqlalchemy import text
120
+
121
+ engine = create_async_engine("postgresql+psycopg://localhost:5432/USER")
122
+ SessionLocal = async_sessionmaker(engine, class_=AsyncSession)
123
+
124
+ async def query():
125
+ async with SessionLocal() as session:
126
+ result = await session.execute(text("SELECT * FROM MyTable"))
127
+ return result.fetchall()
128
+ ```
129
+
130
+ ### COPY bulk load
131
+
132
+ ```python
133
+ with conn.cursor() as cur:
134
+ with cur.copy("COPY MyTable (col1, col2) FROM STDIN") as copy:
135
+ for row in data:
136
+ copy.write_row(row)
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Documentation
142
+
143
+ | Guide | Description |
144
+ | ------------------------------------------------------ | ------------------------------------------ |
145
+ | [Installation](docs/INSTALLATION.md) | Docker, PyPI, Embedded Python deployment |
146
+ | [Architecture](docs/ARCHITECTURE.md) | System design, dual backend, request flow |
147
+ | [DDL Compatibility](docs/DDL_COMPATIBILITY.md) | PostgreSQL DDL transformations |
148
+ | [Vector Operations](docs/VECTOR_PARAMETER_BINDING.md) | pgvector syntax, HNSW indexes |
149
+ | [Client Compatibility](docs/CLIENT_RECOMMENDATIONS.md) | Per-language setup and caveats |
150
+ | [Deployment](docs/DEPLOYMENT.md) | Production setup, SSL/TLS, auth |
151
+ | [Performance](docs/PERFORMANCE.md) | Benchmarks, tuning |
152
+ | [Developer Guide](docs/developer_guide.md) | Development setup, contribution guidelines |
153
+
154
+ ---
155
+
156
+ ## Development
157
+
158
+ ```bash
159
+ # Install dependencies
160
+ uv sync --frozen
161
+
162
+ # Run unit + contract tests (no IRIS needed)
163
+ pytest tests/unit/ tests/contract/ -v
164
+
165
+ # Run with live IRIS (container must be up)
166
+ docker compose up -d
167
+ PGWIRE_BACKEND_TYPE=dbapi PGWIRE_POOL_SIZE=1 pytest tests/ -v
168
+
169
+ # Code quality check
170
+ python -m iris_pgwire.quality
171
+ ```
172
+
173
+ **Test coverage**: 92% (5349 tests)
174
+ **Code quality**: black (formatter), ruff (linter), bandit (security)
175
+
176
+ ---
177
+
178
+ ## Known Limitations
179
+
180
+ See [KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md) for the full list. Key items:
181
+
182
+ - IRIS Community Edition: 5-user connection limit — use `PGWIRE_POOL_SIZE=1` for dev
183
+ - No native SSL termination — use nginx/HAProxy in front for TLS
184
+ - Kerberos/GSSAPI auth wiring deferred (OAuth 2.0 is the recommended enterprise auth)
185
+ - `INFORMATION_SCHEMA` only, no `pg_catalog` tables (translated automatically)
186
+
187
+ ---
188
+
189
+ ## Contributing
190
+
191
+ ```bash
192
+ git clone https://github.com/intersystems-community/iris-pgwire.git
193
+ cd iris-pgwire
194
+ uv sync --frozen
195
+ docker compose up -d
196
+ pytest tests/unit/ tests/contract/ -v
197
+ ```
198
+
199
+ Open an issue or PR on [GitHub](https://github.com/intersystems-community/iris-pgwire/issues).
200
+
201
+ ---
202
+
203
+ ## Links
204
+
205
+ - [InterSystems IRIS](https://www.intersystems.com/products/intersystems-iris/)
206
+ - [IRIS Documentation](https://docs.intersystems.com/iris/)
207
+ - [PostgreSQL Protocol Spec](https://www.postgresql.org/docs/current/protocol.html)
208
+ - [pgvector](https://github.com/pgvector/pgvector)
209
+
210
+ ---
211
+
212
+ MIT License — see [LICENSE](LICENSE)
@@ -99,6 +99,9 @@ iris = [
99
99
  # IRIS embedded Python (when available)
100
100
  # "intersystems-iris>=3.6.0",
101
101
  ]
102
+ ai = [
103
+ "iris-agentic-dev>=1.0",
104
+ ]
102
105
  kerberos = [
103
106
  # Kerberos GSSAPI authentication (optional - not implemented in wire protocol yet)
104
107
  # Install with: pip install iris-pgwire[kerberos]
@@ -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.5.7"
9
+ __version__ = "1.5.9"
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
@@ -156,16 +156,18 @@ class DBAPIExecutor:
156
156
  return value
157
157
 
158
158
  date_part, time_part = ts_match.group(1), ts_match.group(2)
159
- tz_sign, tz_hh, tz_mm = ts_match.group(4), ts_match.group(5), ts_match.group(6)
159
+ tz_sign, tz_hh = ts_match.group(4), ts_match.group(5)
160
160
 
161
+ # Strip timezone — IRIS doesn't support tz-aware timestamps; keep local time as-is
161
162
  if not (tz_sign and tz_hh):
162
163
  return f"{date_part} {time_part}"
163
164
 
164
- offset_mins = (int(tz_hh) * 60 + int(tz_mm or 0)) * (1 if tz_sign == "+" else -1)
165
- fmt = "%Y-%m-%d %H:%M:%S.%f" if "." in time_part else "%Y-%m-%d %H:%M:%S"
166
- naive = dt.datetime.strptime(f"{date_part} {time_part}", fmt)
167
- utc = naive - dt.timedelta(minutes=offset_mins)
168
- return utc.strftime(fmt)
165
+ has_frac = "." in time_part
166
+ result = f"{date_part} {time_part}"
167
+ if has_frac and "." in result:
168
+ base, frac = result.rsplit(".", 1)
169
+ result = base + "." + frac[:3]
170
+ return result
169
171
 
170
172
  # ------------------------------------------------------------------
171
173
  # Query execution
@@ -538,7 +540,39 @@ class DBAPIExecutor:
538
540
  """Fetch rows and column metadata from a cursor with results."""
539
541
  if not cursor.description:
540
542
  return [], []
541
- return cursor.fetchall(), self._build_metadata_from_description(cursor.description)
543
+ rows = cursor.fetchall()
544
+ columns = self._build_metadata_from_description(cursor.description)
545
+ if rows:
546
+ columns = self._refine_column_types_from_rows(columns, rows)
547
+ return rows, columns
548
+
549
+ def _refine_column_types_from_rows(
550
+ self, columns: list[dict], rows: list
551
+ ) -> list[dict]:
552
+ """Refine column type OIDs using actual first-row Python values.
553
+
554
+ IRIS DBAPI often returns type_code=4 for all columns regardless of type.
555
+ Use the actual Python type of the first row's values to assign correct OIDs.
556
+ Only refines columns that currently have the generic VARCHAR OID (1043).
557
+ """
558
+ if not rows or not columns:
559
+ return columns
560
+ first_row = rows[0]
561
+ refined = []
562
+ for i, col in enumerate(columns):
563
+ if col.get("type_oid") == 1043 and i < len(first_row):
564
+ val = first_row[i]
565
+ if isinstance(val, bool):
566
+ refined.append({**col, "type_oid": 16}) # BOOL
567
+ elif isinstance(val, int):
568
+ refined.append({**col, "type_oid": 23}) # INT4
569
+ elif isinstance(val, float):
570
+ refined.append({**col, "type_oid": 701}) # FLOAT8
571
+ else:
572
+ refined.append(col)
573
+ else:
574
+ refined.append(col)
575
+ return refined
542
576
 
543
577
  # ------------------------------------------------------------------
544
578
  # ON CONFLICT handling
@@ -913,7 +947,11 @@ class DBAPIExecutor:
913
947
  cur.execute(query, tuple(query_params))
914
948
  else:
915
949
  cur.execute(query)
916
- return cur.fetchall(), self._build_metadata_from_description(cur.description)
950
+ rows = cur.fetchall()
951
+ columns = self._build_metadata_from_description(cur.description)
952
+ if rows:
953
+ columns = self._refine_column_types_from_rows(columns, rows)
954
+ return rows, columns
917
955
  finally:
918
956
  try:
919
957
  cur.close()
@@ -348,7 +348,7 @@ class IntegratedMLExecutor:
348
348
  async def handle_system_function_query(self, sql: str) -> tuple[list[dict], list[str]]:
349
349
  """Handle queries with IRIS system functions"""
350
350
  # Check if this is a simple system function call we can handle
351
- if "%SYSTEM.ML.%ModelExists" in sql.upper():
351
+ if "%SYSTEM.ML.%MODELEXISTS" in sql.upper():
352
352
  # Extract model name and check existence
353
353
  # For now, return mock data - in production this would query IRIS metadata
354
354
  return [{"model_exists": True}], ["model_exists"]