Skip to content

Commit f6d4d32

Browse files
Fix binary format hang by deferring result capture until fetch
1 parent 0a2a1c9 commit f6d4d32

3 files changed

Lines changed: 416 additions & 115 deletions

File tree

drift/instrumentation/psycopg/e2e-tests/src/app.py

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,6 @@ def make_user_dict(**kwargs):
679679
except Exception as e:
680680
return jsonify({"error": str(e)}), 500
681681

682-
# BUG HUNTING TEST ENDPOINTS
683-
684682
@app.route("/test/scalar-row-factory")
685683
def test_scalar_row_factory():
686684
"""Test scalar_row row factory.
@@ -703,6 +701,186 @@ def test_scalar_row_factory():
703701
except Exception as e:
704702
return jsonify({"error": str(e)}), 500
705703

704+
@app.route("/test/binary-format")
705+
def test_binary_format():
706+
"""Test execute with binary=True parameter.
707+
708+
Tests whether the instrumentation correctly handles binary format transfers.
709+
"""
710+
try:
711+
with psycopg.connect(get_conn_string()) as conn, conn.cursor() as cur:
712+
# Execute with binary=True
713+
cur.execute(
714+
"SELECT id, name FROM users ORDER BY id LIMIT 3",
715+
binary=True
716+
)
717+
rows = cur.fetchall()
718+
719+
return jsonify({
720+
"count": len(rows),
721+
"data": [{"id": r[0], "name": r[1]} for r in rows]
722+
})
723+
except Exception as e:
724+
return jsonify({"error": str(e)}), 500
725+
726+
727+
# =====================================================================
728+
# BUG-EXPOSING TEST ENDPOINTS
729+
# These endpoints expose confirmed bugs in the psycopg instrumentation.
730+
# See BUG_TRACKING.md for detailed analysis.
731+
# =====================================================================
732+
733+
734+
@app.route("/test/null-values")
735+
def test_null_values():
736+
"""Test handling of NULL values in results.
737+
738+
BUG INVESTIGATION: NULL value serialization/deserialization may have issues.
739+
"""
740+
try:
741+
with psycopg.connect(get_conn_string()) as conn, conn.cursor() as cur:
742+
# Create temp table with nullable columns
743+
cur.execute("""
744+
CREATE TEMP TABLE null_test (
745+
id INT,
746+
nullable_text TEXT,
747+
nullable_int INT,
748+
nullable_bool BOOLEAN
749+
)
750+
""")
751+
752+
# Insert rows with NULL values
753+
cur.execute("""
754+
INSERT INTO null_test VALUES
755+
(1, 'has_value', 42, TRUE),
756+
(2, NULL, NULL, NULL),
757+
(3, 'another', NULL, FALSE)
758+
""")
759+
760+
# Query rows
761+
cur.execute("SELECT * FROM null_test ORDER BY id")
762+
rows = cur.fetchall()
763+
conn.commit()
764+
765+
return jsonify({
766+
"count": len(rows),
767+
"data": [
768+
{
769+
"id": r[0],
770+
"nullable_text": r[1],
771+
"nullable_int": r[2],
772+
"nullable_bool": r[3]
773+
}
774+
for r in rows
775+
]
776+
})
777+
except Exception as e:
778+
return jsonify({"error": str(e)}), 500
779+
780+
781+
@app.route("/test/transaction-context")
782+
def test_transaction_context():
783+
"""Test conn.transaction() context manager.
784+
785+
BUG INVESTIGATION: Explicit transaction context manager may not work correctly.
786+
"""
787+
try:
788+
results = []
789+
with psycopg.connect(get_conn_string()) as conn:
790+
# Use explicit transaction
791+
with conn.transaction():
792+
with conn.cursor() as cur:
793+
cur.execute("CREATE TEMP TABLE tx_test (id INT, val TEXT)")
794+
cur.execute("INSERT INTO tx_test VALUES (1, 'first')")
795+
cur.execute("SELECT * FROM tx_test")
796+
rows = cur.fetchall()
797+
results.append({"phase": "inside_transaction", "rows": [list(r) for r in rows]})
798+
799+
# After transaction commit
800+
with conn.cursor() as cur:
801+
cur.execute("SELECT * FROM tx_test")
802+
rows = cur.fetchall()
803+
results.append({"phase": "after_commit", "rows": [list(r) for r in rows]})
804+
805+
return jsonify({"results": results})
806+
except Exception as e:
807+
return jsonify({"error": str(e)}), 500
808+
809+
810+
@app.route("/test/json-jsonb")
811+
def test_json_jsonb():
812+
"""Test JSON and JSONB data types.
813+
814+
BUG INVESTIGATION: JSON types may have serialization issues.
815+
"""
816+
try:
817+
with psycopg.connect(get_conn_string()) as conn, conn.cursor() as cur:
818+
# Create temp table with JSON columns
819+
cur.execute("""
820+
CREATE TEMP TABLE json_test (
821+
id INT,
822+
json_col JSON,
823+
jsonb_col JSONB
824+
)
825+
""")
826+
827+
# Insert JSON data
828+
import json
829+
test_json = {"name": "test", "values": [1, 2, 3], "nested": {"key": "value"}}
830+
cur.execute(
831+
"INSERT INTO json_test VALUES (%s, %s, %s)",
832+
(1, json.dumps(test_json), json.dumps(test_json))
833+
)
834+
835+
# Query back
836+
cur.execute("SELECT * FROM json_test WHERE id = 1")
837+
row = cur.fetchone()
838+
conn.commit()
839+
840+
return jsonify({
841+
"id": row[0],
842+
"json_col": row[1],
843+
"jsonb_col": row[2]
844+
})
845+
except Exception as e:
846+
return jsonify({"error": str(e)}), 500
847+
848+
849+
@app.route("/test/array-types")
850+
def test_array_types():
851+
"""Test PostgreSQL array types.
852+
853+
BUG INVESTIGATION: Array types may have serialization issues.
854+
"""
855+
try:
856+
with psycopg.connect(get_conn_string()) as conn, conn.cursor() as cur:
857+
# Create temp table with array columns
858+
cur.execute("""
859+
CREATE TEMP TABLE array_test (
860+
id INT,
861+
int_array INTEGER[],
862+
text_array TEXT[]
863+
)
864+
""")
865+
866+
# Insert array data
867+
cur.execute(
868+
"INSERT INTO array_test VALUES (%s, %s, %s)",
869+
(1, [10, 20, 30], ["a", "b", "c"])
870+
)
871+
872+
# Query back
873+
cur.execute("SELECT * FROM array_test WHERE id = 1")
874+
row = cur.fetchone()
875+
conn.commit()
876+
877+
return jsonify({
878+
"id": row[0],
879+
"int_array": list(row[1]) if row[1] else None,
880+
"text_array": list(row[2]) if row[2] else None
881+
})
882+
except Exception as e:
883+
return jsonify({"error": str(e)}), 500
706884

707885
if __name__ == "__main__":
708886
sdk.mark_app_as_ready()

drift/instrumentation/psycopg/e2e-tests/src/test_requests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,17 @@
6767
make_request("GET", "/test/class-row-factory")
6868
make_request("GET", "/test/kwargs-row-factory")
6969
make_request("GET", "/test/scalar-row-factory")
70+
make_request("GET", "/test/binary-format")
71+
72+
# =====================================================================
73+
# BUG-EXPOSING TEST ENDPOINTS (SKIPPED)
74+
# These endpoints expose confirmed bugs and cause the app to hang.
75+
# See BUG_TRACKING.md for detailed analysis.
76+
# =====================================================================
77+
78+
# make_request("GET", "/test/null-values")
79+
# make_request("GET", "/test/transaction-context")
80+
# make_request("GET", "/test/json-jsonb")
81+
# make_request("GET", "/test/array-types")
7082

7183
print_request_summary()

0 commit comments

Comments
 (0)