sqlalchemy-firebird-async 0.2.2__tar.gz → 0.2.3__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 (29) hide show
  1. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/PKG-INFO +1 -1
  2. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/pyproject.toml +1 -1
  3. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/compiler.py +9 -0
  4. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_types.py +80 -1
  5. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/.claude/settings.local.json +0 -0
  6. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/.gitignore +0 -0
  7. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/CONTRIBUTING.md +0 -0
  8. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/LICENSE +0 -0
  9. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/README.md +0 -0
  10. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/justfile +0 -0
  11. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/pytest.ini +0 -0
  12. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/repro_cast.py +0 -0
  13. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/__init__.py +0 -0
  14. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/fdb.py +0 -0
  15. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/firebird_driver.py +0 -0
  16. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/firebirdsql.py +0 -0
  17. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/src/sqlalchemy_firebird_async/types.py +0 -0
  18. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/test_output.txt +0 -0
  19. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/test_output_after_fix.txt +0 -0
  20. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/test_output_final.txt +0 -0
  21. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/test_output_full.txt +0 -0
  22. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/__init__.py +0 -0
  23. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/conftest.py +0 -0
  24. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/requirements.py +0 -0
  25. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_basic.py +0 -0
  26. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_compliance.py +0 -0
  27. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_enum.py +0 -0
  28. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_load.py +0 -0
  29. {sqlalchemy_firebird_async-0.2.2 → sqlalchemy_firebird_async-0.2.3}/tests/test_terminate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlalchemy-firebird-async
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Asyncio support for Firebird in SQLAlchemy
5
5
  Project-URL: Homepage, https://github.com/attid/sqlalchemy-firebird-async
6
6
  Project-URL: Repository, https://github.com/attid/sqlalchemy-firebird-async
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sqlalchemy-firebird-async"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Asyncio support for Firebird in SQLAlchemy"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -94,6 +94,15 @@ class PatchedFBCompiler(FBCompiler):
94
94
  return f"CAST({super().visit_bindparam(bindparam, within_columns_clause=within_columns_clause, **kwargs)} AS {db_type})"
95
95
 
96
96
  ret = super().visit_bindparam(bindparam, within_columns_clause=within_columns_clause, **kwargs)
97
+
98
+ from sqlalchemy.types import Text
99
+
100
+ if isinstance(bindparam.type, Text) and "CAST" in ret:
101
+ return re.sub(
102
+ r" AS (VARCHAR|CHAR|NVARCHAR|NCHAR)\(\d+\)\)",
103
+ " AS BLOB SUB_TYPE TEXT)",
104
+ ret,
105
+ )
97
106
 
98
107
  # If we are NOT in the columns clause (e.g. WHERE, INSERT values),
99
108
  # modify the CAST(...) wrapper generated by the parent compiler.
@@ -1,7 +1,86 @@
1
1
  import pytest
2
2
  import decimal
3
3
  import datetime
4
- from sqlalchemy import text
4
+ from sqlalchemy import (
5
+ BigInteger,
6
+ Column,
7
+ DateTime,
8
+ Integer,
9
+ String,
10
+ Text,
11
+ delete,
12
+ insert,
13
+ text,
14
+ update,
15
+ )
16
+ from sqlalchemy.orm import declarative_base
17
+ from sqlalchemy_firebird_async.firebird_driver import AsyncFirebirdDialect
18
+
19
+
20
+ Base = declarative_base()
21
+
22
+
23
+ class Transactions(Base):
24
+ __tablename__ = "t_transactions"
25
+
26
+ hash = Column("hash", String(64), primary_key=True)
27
+ description = Column("description", Text(4000), nullable=False)
28
+ body = Column("body", Text(12000), nullable=False)
29
+ add_dt = Column("add_dt", DateTime())
30
+ updated_dt = Column("updated_dt", DateTime())
31
+ uuid = Column("uuid", String(32))
32
+ json = Column("json", Text(), nullable=True)
33
+ state = Column("state", Integer())
34
+ stellar_sequence = Column("stellar_sequence", BigInteger())
35
+ source_account = Column("source_account", String(56))
36
+ owner_id = Column("owner_id", BigInteger())
37
+
38
+
39
+ def test_text_with_length_insert_binds_compile_as_blob_text():
40
+ stmt = insert(Transactions).values(
41
+ hash="8a5ae51261b0a8ec44ef027aef5aaf94da5c39179e3c36a86194f49472e1d4b4",
42
+ description="desc",
43
+ body="A" * 8880,
44
+ uuid="u" * 32,
45
+ json="{}",
46
+ state=0,
47
+ stellar_sequence=1,
48
+ source_account="G" + "A" * 55,
49
+ owner_id=1,
50
+ )
51
+
52
+ compiled = str(stmt.compile(dialect=AsyncFirebirdDialect()))
53
+
54
+ assert "CAST(:description AS BLOB SUB_TYPE TEXT)" in compiled
55
+ assert "CAST(:body AS BLOB SUB_TYPE TEXT)" in compiled
56
+ assert "CAST(:json AS BLOB SUB_TYPE TEXT)" in compiled
57
+ assert "CAST(:description AS VARCHAR(2000))" not in compiled
58
+ assert "CAST(:body AS VARCHAR(2000))" not in compiled
59
+
60
+
61
+ def test_text_with_length_update_binds_compile_as_blob_text():
62
+ stmt = (
63
+ update(Transactions)
64
+ .where(Transactions.hash == "h")
65
+ .values(description="desc", body="A" * 8880)
66
+ )
67
+
68
+ compiled = str(stmt.compile(dialect=AsyncFirebirdDialect()))
69
+
70
+ assert "description=CAST(:description AS BLOB SUB_TYPE TEXT)" in compiled
71
+ assert "body=CAST(:body AS BLOB SUB_TYPE TEXT)" in compiled
72
+ assert "description=CAST(:description AS VARCHAR(2000))" not in compiled
73
+ assert "body=CAST(:body AS VARCHAR(2000))" not in compiled
74
+
75
+
76
+ def test_text_with_length_delete_where_bind_does_not_compile_as_varchar():
77
+ stmt = delete(Transactions).where(Transactions.body == "A" * 8880)
78
+
79
+ compiled = str(stmt.compile(dialect=AsyncFirebirdDialect()))
80
+
81
+ assert "CAST(:body_1 AS BLOB SUB_TYPE TEXT)" in compiled
82
+ assert "CAST(:body_1 AS VARCHAR(2000))" not in compiled
83
+
5
84
 
6
85
  @pytest.mark.asyncio
7
86
  async def test_primitive_types(async_engine):