iris-pgwire 1.5.8__tar.gz → 1.7.0__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.
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/.gitignore +36 -0
- iris_pgwire-1.7.0/PKG-INFO +297 -0
- iris_pgwire-1.7.0/README.md +212 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/pyproject.toml +9 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/__init__.py +1 -1
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/_reentrancy.py +27 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/catalog_router.py +158 -15
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/function_installer.py +103 -0
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/functions.py +566 -0
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/views/__init__.py +18 -0
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/views/definitions.py +731 -0
- iris_pgwire-1.7.0/src/iris_pgwire/catalog/views/installer.py +98 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/dbapi_executor.py +199 -12
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/integratedml.py +1 -1
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/iris_executor.py +335 -29
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/protocol.py +81 -23
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/code_quality_validator.py +12 -7
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/package_metadata_validator.py +8 -4
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/security_validator.py +11 -8
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/schema_mapper.py +59 -1
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/server.py +46 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/array_literal.py +71 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/array_params.py +287 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/boolean_expr.py +355 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/boolean_translator.py +16 -16
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/column_types.py +197 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/identifier_normalizer.py +1 -2
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/normalizer.py +99 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/pg_array.py +99 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/pg_functions.py +137 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/refiner.py +25 -8
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/sqlstate.py +177 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/statement_filter.py +10 -0
- iris_pgwire-1.7.0/src/iris_pgwire/sql_translator/verbatim.py +49 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/vector_optimizer.py +75 -0
- iris_pgwire-1.5.8/PKG-INFO +0 -372
- iris_pgwire-1.5.8/README.md +0 -288
- iris_pgwire-1.5.8/src/iris_pgwire/auth/AGENTS.md +0 -38
- iris_pgwire-1.5.8/src/iris_pgwire/catalog/AGENTS.md +0 -44
- iris_pgwire-1.5.8/src/iris_pgwire/conversions/AGENTS.md +0 -31
- iris_pgwire-1.5.8/src/iris_pgwire/quality/AGENTS.md +0 -32
- iris_pgwire-1.5.8/src/iris_pgwire/sql_translator/AGENTS.md +0 -96
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/LICENSE +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/_column_naming.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/_noop_cursor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/_result_processing.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/_type_mapping.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/auth_selector.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/gssapi_auth.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/oauth_bridge.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/scram.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/auth/wallet_credentials.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/backend_selector.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/bulk_executor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/catalog_functions.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/oid_generator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_attrdef.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_attribute.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_class.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_constraint.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_index.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_namespace.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/catalog/pg_type.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/column_validator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/config.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/config_schema.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/constitutional.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/bulk_insert.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/date_horolog.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/ddl_idempotency.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/ddl_splitter.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/json_path.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/conversions/vector_syntax.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/copy_handler.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/csv_processor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/dbapi_connection_pool.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/debug_tracer.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/health_checker.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/iris_constructs.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/iris_log_handler.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/iris_user_management.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/migrations/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/migrations/__main__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/migrations/executor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/backend_config.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/connection_pool_state.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/dbapi_connection.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/ipm_metadata.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/models/vector_query_request.py +1 -1
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/observability.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/performance_monitor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/__main__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/documentation_validator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/quality/validator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/alias_extractor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/api.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/cache.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/confidence_analyzer.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/config.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/constraint_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/copy_parser.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/date_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/ddl_parser.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/ddl_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/debug.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/default_values.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/enum_registry.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/enum_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/error_handler.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/index_validator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/interceptor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/logging_config.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/mappings/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/mappings/constructs.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/mappings/datatypes.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/mappings/document_filters.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/mappings/functions.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/metadata_cache.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/metrics.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/models.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/parser.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/performance_monitor.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/pipeline.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/reserved_words.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/returning_plan.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/skipped_table_set.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/transaction_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/type_translator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/sql_translator/validator.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/testing/__init__.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/testing/base_fixture_builder.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/type_mapping.py +0 -0
- {iris_pgwire-1.5.8 → iris_pgwire-1.7.0}/src/iris_pgwire/vector_metrics.py +0 -0
|
@@ -79,3 +79,39 @@ 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
|
+
CODEX.md
|
|
98
|
+
TABNINE.md
|
|
99
|
+
|
|
100
|
+
# Root-level debug/scratch scripts (use scripts/ directory instead)
|
|
101
|
+
check_intersystems.py
|
|
102
|
+
check_iris.py
|
|
103
|
+
check_resolve.py
|
|
104
|
+
find_shadowing.py
|
|
105
|
+
inspect_monkeypatch.py
|
|
106
|
+
repro_scoping.py
|
|
107
|
+
test_conn.py
|
|
108
|
+
test_connection_stability.py
|
|
109
|
+
test_pg_type.py
|
|
110
|
+
test_scope.py
|
|
111
|
+
update_article.py
|
|
112
|
+
verify_demo.sql
|
|
113
|
+
|
|
114
|
+
# iris-agentic-dev local connection config (per-developer: host, port, container
|
|
115
|
+
# name and credentials vary by machine). Template is committed at
|
|
116
|
+
# specs/043-local-first-sync/spikes/iris-agentic-dev.toml.example
|
|
117
|
+
.iris-agentic-dev.toml
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: iris-pgwire
|
|
3
|
+
Version: 1.7.0
|
|
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
|
+
Provides-Extra: dev
|
|
66
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
67
|
+
Requires-Dist: mypy>=1.5.0; extra == 'dev'
|
|
68
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
69
|
+
Provides-Extra: iris
|
|
70
|
+
Provides-Extra: kerberos
|
|
71
|
+
Requires-Dist: gssapi>=1.8.0; extra == 'kerberos'
|
|
72
|
+
Provides-Extra: test
|
|
73
|
+
Requires-Dist: docker>=6.0.0; extra == 'test'
|
|
74
|
+
Requires-Dist: iris-devtester>=0.1.0; extra == 'test'
|
|
75
|
+
Requires-Dist: k5test>=0.10.3; extra == 'test'
|
|
76
|
+
Requires-Dist: psycopg[binary]>=3.1.0; extra == 'test'
|
|
77
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
|
|
78
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
|
|
79
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
|
|
80
|
+
Requires-Dist: pytest-fixtures>=3.0.0; extra == 'test'
|
|
81
|
+
Requires-Dist: pytest-timeout>=2.2.0; extra == 'test'
|
|
82
|
+
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
|
83
|
+
Requires-Dist: sqlparse>=0.4.0; extra == 'test'
|
|
84
|
+
Description-Content-Type: text/markdown
|
|
85
|
+
|
|
86
|
+
# iris-pgwire
|
|
87
|
+
|
|
88
|
+
[](https://opensource.org/licenses/MIT)
|
|
89
|
+
[](https://www.python.org/downloads/)
|
|
90
|
+
[](https://github.com/intersystems-community/iris-pgwire)
|
|
91
|
+
|
|
92
|
+
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.
|
|
93
|
+
|
|
94
|
+
**Connection string**: `postgresql://user:pass@localhost:5432/USER`
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Quick Start
|
|
99
|
+
|
|
100
|
+
### Docker (recommended)
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git clone https://github.com/intersystems-community/iris-pgwire.git
|
|
104
|
+
cd iris-pgwire
|
|
105
|
+
docker compose up -d
|
|
106
|
+
|
|
107
|
+
# Test it (PGWire runs on port 5432 inside the IRIS container)
|
|
108
|
+
psql -h localhost -p 5432 -U _SYSTEM -d USER -c "SELECT 'Hello from IRIS!'"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Python package
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install iris-pgwire psycopg[binary]
|
|
115
|
+
|
|
116
|
+
export IRIS_HOST=localhost IRIS_PORT=1972 \
|
|
117
|
+
IRIS_USERNAME=_SYSTEM IRIS_PASSWORD=SYS IRIS_NAMESPACE=USER
|
|
118
|
+
|
|
119
|
+
python -m iris_pgwire.server
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### First query
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import psycopg
|
|
126
|
+
|
|
127
|
+
with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
|
|
128
|
+
with conn.cursor() as cur:
|
|
129
|
+
cur.execute("SELECT COUNT(*) FROM MyTable")
|
|
130
|
+
print(cur.fetchone()[0])
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Verified Client Compatibility
|
|
136
|
+
|
|
137
|
+
Tested against real IRIS instances via the wire protocol:
|
|
138
|
+
|
|
139
|
+
| Language | Clients |
|
|
140
|
+
| -------- | -------------------------------------------- |
|
|
141
|
+
| Python | psycopg3, asyncpg, SQLAlchemy (sync + async) |
|
|
142
|
+
| Node.js | pg (node-postgres) |
|
|
143
|
+
| Java | PostgreSQL JDBC |
|
|
144
|
+
| .NET | Npgsql |
|
|
145
|
+
| Go | pgx v5 |
|
|
146
|
+
| Ruby | pg gem |
|
|
147
|
+
| Rust | tokio-postgres |
|
|
148
|
+
| PHP | PDO PostgreSQL |
|
|
149
|
+
|
|
150
|
+
**ORMs**: SQLAlchemy, Prisma, Drizzle, Sequelize, Hibernate
|
|
151
|
+
**BI tools**: Apache Superset, Metabase, Grafana (standard PostgreSQL driver)
|
|
152
|
+
|
|
153
|
+
See [Client Compatibility Guide](docs/CLIENT_RECOMMENDATIONS.md) for setup examples.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Key Features
|
|
158
|
+
|
|
159
|
+
**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).
|
|
160
|
+
|
|
161
|
+
**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).
|
|
162
|
+
|
|
163
|
+
**SQL translation** — `RETURNING` emulation, `ON CONFLICT`, boolean literals, `pg_catalog` → `INFORMATION_SCHEMA` rewrites, JSON operators (`->` / `->>` → `JSON_EXTRACT`), parameterized queries.
|
|
164
|
+
|
|
165
|
+
**Authentication** — SCRAM-SHA-256, OAuth 2.0 (RFC 6749), IRIS Wallet credentials.
|
|
166
|
+
|
|
167
|
+
**Dual backend** — Embedded Python (irispython, lowest latency) or external DBAPI (standard TCP connection). Selectable via `IRIS_BACKEND` env var.
|
|
168
|
+
|
|
169
|
+
**COPY protocol** — Bulk load via `COPY … FROM STDIN` (~600 rows/sec on DBAPI path).
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Usage Examples
|
|
174
|
+
|
|
175
|
+
### Parameterized queries (psycopg3)
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import psycopg
|
|
179
|
+
|
|
180
|
+
with psycopg.connect("host=localhost port=5432 dbname=USER user=_SYSTEM password=SYS") as conn:
|
|
181
|
+
with conn.cursor() as cur:
|
|
182
|
+
cur.execute("SELECT * FROM MyTable WHERE id = %s", (42,))
|
|
183
|
+
row = cur.fetchone()
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Vector similarity search
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
query_vector = [0.1, 0.2, 0.3]
|
|
190
|
+
with conn.cursor() as cur:
|
|
191
|
+
cur.execute("""
|
|
192
|
+
SELECT id, embedding <=> %s::vector AS score
|
|
193
|
+
FROM vectors
|
|
194
|
+
ORDER BY score
|
|
195
|
+
LIMIT 5
|
|
196
|
+
""", (query_vector,))
|
|
197
|
+
results = cur.fetchall()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Async SQLAlchemy
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
|
204
|
+
from sqlalchemy import text
|
|
205
|
+
|
|
206
|
+
engine = create_async_engine("postgresql+psycopg://localhost:5432/USER")
|
|
207
|
+
SessionLocal = async_sessionmaker(engine, class_=AsyncSession)
|
|
208
|
+
|
|
209
|
+
async def query():
|
|
210
|
+
async with SessionLocal() as session:
|
|
211
|
+
result = await session.execute(text("SELECT * FROM MyTable"))
|
|
212
|
+
return result.fetchall()
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### COPY bulk load
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
with conn.cursor() as cur:
|
|
219
|
+
with cur.copy("COPY MyTable (col1, col2) FROM STDIN") as copy:
|
|
220
|
+
for row in data:
|
|
221
|
+
copy.write_row(row)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Documentation
|
|
227
|
+
|
|
228
|
+
| Guide | Description |
|
|
229
|
+
| ------------------------------------------------------ | ------------------------------------------ |
|
|
230
|
+
| [Installation](docs/INSTALLATION.md) | Docker, PyPI, Embedded Python deployment |
|
|
231
|
+
| [Architecture](docs/ARCHITECTURE.md) | System design, dual backend, request flow |
|
|
232
|
+
| [DDL Compatibility](docs/DDL_COMPATIBILITY.md) | PostgreSQL DDL transformations |
|
|
233
|
+
| [Vector Operations](docs/VECTOR_PARAMETER_BINDING.md) | pgvector syntax, HNSW indexes |
|
|
234
|
+
| [Client Compatibility](docs/CLIENT_RECOMMENDATIONS.md) | Per-language setup and caveats |
|
|
235
|
+
| [Deployment](docs/DEPLOYMENT.md) | Production setup, SSL/TLS, auth |
|
|
236
|
+
| [Performance](docs/PERFORMANCE.md) | Benchmarks, tuning |
|
|
237
|
+
| [Developer Guide](docs/developer_guide.md) | Development setup, contribution guidelines |
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Development
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
# Install dependencies
|
|
245
|
+
uv sync --frozen
|
|
246
|
+
|
|
247
|
+
# Run unit + contract tests (no IRIS needed)
|
|
248
|
+
pytest tests/unit/ tests/contract/ -v
|
|
249
|
+
|
|
250
|
+
# Run with live IRIS (container must be up)
|
|
251
|
+
docker compose up -d
|
|
252
|
+
PGWIRE_BACKEND_TYPE=dbapi PGWIRE_POOL_SIZE=1 pytest tests/ -v
|
|
253
|
+
|
|
254
|
+
# Code quality check
|
|
255
|
+
python -m iris_pgwire.quality
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Test coverage**: 92% (5349 tests)
|
|
259
|
+
**Code quality**: black (formatter), ruff (linter), bandit (security)
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Known Limitations
|
|
264
|
+
|
|
265
|
+
See [KNOWN_LIMITATIONS.md](KNOWN_LIMITATIONS.md) for the full list. Key items:
|
|
266
|
+
|
|
267
|
+
- IRIS Community Edition: 5-user connection limit — use `PGWIRE_POOL_SIZE=1` for dev
|
|
268
|
+
- No native SSL termination — use nginx/HAProxy in front for TLS
|
|
269
|
+
- Kerberos/GSSAPI auth wiring deferred (OAuth 2.0 is the recommended enterprise auth)
|
|
270
|
+
- `INFORMATION_SCHEMA` only, no `pg_catalog` tables (translated automatically)
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Contributing
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
git clone https://github.com/intersystems-community/iris-pgwire.git
|
|
278
|
+
cd iris-pgwire
|
|
279
|
+
uv sync --frozen
|
|
280
|
+
docker compose up -d
|
|
281
|
+
pytest tests/unit/ tests/contract/ -v
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Open an issue or PR on [GitHub](https://github.com/intersystems-community/iris-pgwire/issues).
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Links
|
|
289
|
+
|
|
290
|
+
- [InterSystems IRIS](https://www.intersystems.com/products/intersystems-iris/)
|
|
291
|
+
- [IRIS Documentation](https://docs.intersystems.com/iris/)
|
|
292
|
+
- [PostgreSQL Protocol Spec](https://www.postgresql.org/docs/current/protocol.html)
|
|
293
|
+
- [pgvector](https://github.com/pgvector/pgvector)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
MIT License — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# iris-pgwire
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](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,15 @@ iris = [
|
|
|
99
99
|
# IRIS embedded Python (when available)
|
|
100
100
|
# "intersystems-iris>=3.6.0",
|
|
101
101
|
]
|
|
102
|
+
ai = [
|
|
103
|
+
# IRIS-aware agent tooling. iris-agentic-dev is a Rust binary and is NOT
|
|
104
|
+
# published on PyPI, so it cannot be declared as a dependency here — doing
|
|
105
|
+
# so made `pip install iris-pgwire[ai]` fail outright. Install it directly:
|
|
106
|
+
# Linux: curl -fsSL https://github.com/intersystems-community/iris-agentic-dev/releases/latest/download/iris-agentic-dev-linux-x86_64 \
|
|
107
|
+
# -o /usr/local/bin/iris-agentic-dev && chmod +x /usr/local/bin/iris-agentic-dev
|
|
108
|
+
# macOS: brew install https://raw.githubusercontent.com/intersystems-community/iris-agentic-dev/master/Formula/iris-agentic-dev.rb
|
|
109
|
+
# See docs/iris-pgwire-iad-setup-issues.md and AGENTS.md.
|
|
110
|
+
]
|
|
102
111
|
kerberos = [
|
|
103
112
|
# Kerberos GSSAPI authentication (optional - not implemented in wire protocol yet)
|
|
104
113
|
# 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.
|
|
9
|
+
__version__ = "1.7.0"
|
|
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
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Re-entrancy guard for catalog query handling.
|
|
2
|
+
|
|
3
|
+
Lives in its own module because two things need it and importing it from
|
|
4
|
+
`catalog_router` creates a cycle: the router imports the view registry, and the
|
|
5
|
+
view installer needs the guard.
|
|
6
|
+
|
|
7
|
+
Some handlers answer a catalog query by issuing their own SQL through the
|
|
8
|
+
executor — `_build_pg_class_response` asks IRIS for `INFORMATION_SCHEMA.TABLES`.
|
|
9
|
+
That inner query re-enters the router, which would intercept it and return zero
|
|
10
|
+
rows, leaving the handler with nothing to report. The view installer has the
|
|
11
|
+
same problem in a sharper form: its `CREATE VIEW pg_catalog.pg_class AS ...` was
|
|
12
|
+
handed to the pg_class handler, which answered it with a synthetic success — so
|
|
13
|
+
installation reported success while creating nothing.
|
|
14
|
+
|
|
15
|
+
A ContextVar rather than a flag, so the guard is scoped to the asyncio task and
|
|
16
|
+
one session's internal query cannot suppress interception for a concurrent one.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import contextvars
|
|
22
|
+
|
|
23
|
+
_IN_CATALOG_HANDLER: contextvars.ContextVar[bool] = contextvars.ContextVar(
|
|
24
|
+
"iris_pgwire_in_catalog_handler", default=False
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = ["_IN_CATALOG_HANDLER"]
|