@@ -22,7 +22,11 @@ This package provides a SQLAlchemy dialect that allows you to use psqlpy as the
2222- ** Connection Pooling** : Leverages psqlpy's built-in connection pooling
2323- ** Transaction Support** : Full transaction and savepoint support
2424- ** SSL Support** : Configurable SSL connections
25- - ** Type Support** : Native support for PostgreSQL data types
25+ - ** Advanced Type Support** :
26+ - Native UUID support with efficient caching
27+ - Full JSONB operator support (@>, <@, ?, ?&, ?|, etc.)
28+ - PostgreSQL array types
29+ - Custom type conversion with automatic detection
2630
2731## Installation
2832
@@ -105,6 +109,100 @@ with engine.connect() as conn:
105109 print (row)
106110```
107111
112+ ### UUID Support
113+
114+ The dialect provides native UUID support with automatic conversion:
115+
116+ ``` python
117+ from sqlalchemy import create_engine, Column, text
118+ from sqlalchemy.dialects.postgresql import UUID
119+ import uuid
120+
121+ engine = create_engine(" postgresql+psqlpy://user:password@localhost/testdb" )
122+
123+ # Using UUID columns
124+ with engine.connect() as conn:
125+ # UUID objects are automatically converted
126+ user_id = uuid.uuid4()
127+ conn.execute(
128+ text(" INSERT INTO users (id, name) VALUES (:id, :name)" ),
129+ {" id" : user_id, " name" : " John" }
130+ )
131+
132+ # UUID strings are also supported
133+ conn.execute(
134+ text(" SELECT * FROM users WHERE id = :id" ),
135+ {" id" : " 550e8400-e29b-41d4-a716-446655440000" }
136+ )
137+
138+ # Explicit casting (recommended for clarity)
139+ conn.execute(
140+ text(" SELECT * FROM users WHERE id = :id::UUID" ),
141+ {" id" : user_id}
142+ )
143+ conn.commit()
144+ ```
145+
146+ ### JSONB Support
147+
148+ Full support for PostgreSQL JSONB operators:
149+
150+ ``` python
151+ from sqlalchemy import create_engine, Column, Integer, text
152+ from sqlalchemy.dialects.postgresql import JSONB
153+
154+ engine = create_engine(" postgresql+psqlpy://user:password@localhost/testdb" )
155+
156+ with engine.connect() as conn:
157+ # JSONB contains operator (@>)
158+ conn.execute(
159+ text(" SELECT * FROM products WHERE metadata @> :filter" ),
160+ {" filter" : {" color" : " red" }}
161+ )
162+
163+ # JSONB path operators
164+ conn.execute(
165+ text(" SELECT metadata->>'name' FROM products WHERE id = :id" ),
166+ {" id" : 1 }
167+ )
168+
169+ # JSONB existence operators
170+ conn.execute(
171+ text(" SELECT * FROM products WHERE metadata ? :key" ),
172+ {" key" : " color" }
173+ )
174+ conn.commit()
175+ ```
176+
177+ ### Bulk INSERT Operations
178+
179+ The dialect automatically optimizes bulk INSERT operations:
180+
181+ ``` python
182+ from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData
183+
184+ engine = create_engine(" postgresql+psqlpy://user:password@localhost/testdb" )
185+ metadata = MetaData()
186+
187+ users = Table(' users' , metadata,
188+ Column(' id' , Integer, primary_key = True ),
189+ Column(' name' , String(50 )),
190+ Column(' age' , Integer)
191+ )
192+
193+ # Bulk insert - automatically uses multi-value INSERT
194+ data = [
195+ {" name" : f " User { i} " , " age" : 20 + i}
196+ for i in range (1000 )
197+ ]
198+
199+ with engine.begin() as conn:
200+ # This is converted to a single multi-value INSERT
201+ # INSERT INTO users (name, age) VALUES ($1, $2), ($3, $4), ..., ($1999, $2000)
202+ conn.execute(users.insert(), data)
203+ # ~23x faster than executing 1000 separate INSERT statements!
204+ ```
205+
108206### SQLModel Usage
109207
110208``` python
@@ -238,15 +336,53 @@ For detailed benchmark configuration and results interpretation, see [PERFORMANC
238336
239337The dialect consists of several key components:
240338
241- - ** ` PsqlpyDialect ` ** : Main dialect class that inherits from SQLAlchemy's ` DefaultDialect `
242- - ** ` PsqlpyDBAPI ` ** : DBAPI 2.0 compatible interface wrapper
243- - ** ` PsqlpyConnection ` ** : Connection wrapper that adapts psqlpy connections to DBAPI interface
244- - ** ` PsqlpyCursor ` ** : Cursor implementation for executing queries and fetching results
339+ - ** ` PSQLPyAsyncDialect ` ** (` dialect.py ` ): Main dialect class inheriting from PostgreSQL base dialect
340+ - Handles SQL compilation and type mapping
341+ - Manages connection creation and pooling
342+ - Provides asyncpg-compatible naming conventions for migration
343+
344+ - ** ` PSQLPyAdaptDBAPI ` ** (` dbapi.py ` ): DBAPI 2.0 compliant interface wrapper
345+ - Adapts psqlpy to SQLAlchemy's expected interface
346+ - Provides standard exception hierarchy
347+
348+ - ** ` AsyncAdapt_psqlpy_connection ` ** (` connection.py ` ): Connection adapter
349+ - Bridges psqlpy's async connections to SQLAlchemy's synchronous interface using ` await_only `
350+ - Implements transaction management with savepoint support
351+ - Provides connection health checking with ` ping() ` method
352+
353+ - ** ` AsyncAdapt_psqlpy_cursor ` ** (` connection.py ` ): Cursor implementation
354+ - Handles query execution with parameter binding
355+ - Implements multi-value INSERT optimization for bulk operations
356+ - Supports both regular and server-side cursors
357+ - Automatic conversion of named parameters to positional ($1, $2, etc.)
358+
359+ ** Backward Compatibility** : Aliases ` PsqlpyDialect ` , ` PsqlpyConnection ` , and ` PsqlpyCursor ` are provided for compatibility.
360+
361+ ### Protocol-Level Batching
245362
246- ## Limitations
363+ For UPDATE/DELETE operations within transactions, the dialect uses psqlpy's ` transaction.pipeline() ` :
247364
248- - ** Basic Transaction Support** : Advanced transaction features may need additional implementation
249- - ** Limited Error Mapping** : psqlpy exceptions are currently mapped to generic DBAPI exceptions
365+ ``` python
366+ with engine.begin() as conn:
367+ # These updates are batched into a single network round-trip
368+ conn.execute(users.update().where(users.c.id == 1 ).values(name = " John" ))
369+ conn.execute(users.update().where(users.c.id == 2 ).values(name = " Jane" ))
370+ ```
371+
372+ This reduces network latency by sending multiple commands in a single batch.
373+
374+ ### Type Conversion Caching
375+
376+ - UUID conversion results are cached to avoid repeated parsing
377+ - Parameter type detection uses cached regex patterns
378+ - Prepared statement metadata is cached when possible
379+
380+ For detailed performance benchmarks, run ` make benchmark ` or see [ PERFORMANCE_TEST_README.md] ( PERFORMANCE_TEST_README.md ) .
381+
382+ ## Limitations and Design Considerations
383+
384+ - ** Prepared Statement Reuse** : psqlpy's Python API requires parameters at prepare() time, preventing prepared statement caching like asyncpg.
385+ - ** Error Mapping** : All psqlpy exceptions are mapped to a single ` psqlpy.Error ` class for DBAPI compatibility
250386
251387## Contributing
252388
@@ -271,9 +407,34 @@ This project is licensed under the MIT License - see the LICENSE file for detail
271407
272408## Changelog
273409
274- ### 0.1.0 (2025-07-21)
410+ ### 0.1.0a12 (Current)
411+
412+ ** Performance Optimizations:**
413+ - Implemented multi-value INSERT optimization for bulk operations (23.5x speedup for 100 rows)
414+ - Added transaction.pipeline() support for UPDATE/DELETE batching
415+ - Implemented prepared statement caching with automatic type inference
416+ - Added schema cache invalidation tracking
417+
418+ ** Type Support Enhancements:**
419+ - Native UUID support with efficient byte conversion and caching
420+ - Full JSONB operator support (@>, <@, ?, ?&, ?|, ->, ->>, #>, #>>, ||, -, #-)
421+ - Improved parameter type conversion with caching
422+
423+ ** API Improvements:**
424+ - Added asyncpg-compatible attribute naming for easier migration
425+ - Implemented connection health checking with ping() method
426+ - Added transaction savepoint support
427+ - Improved error messages for UUID casting issues
428+
429+ ** Code Quality:**
430+ - Removed performance tracking overhead
431+ - Optimized connection and cursor implementations
432+ - Enhanced documentation with technical details
433+ - Comprehensive test coverage
434+
435+ ### 0.1.0a11
275436
276- - Initial release
437+ - Initial alpha release
277438- Basic SQLAlchemy dialect implementation
278439- DBAPI 2.0 compatible interface
279440- SQLModel compatibility
0 commit comments