Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions e2e-python/tests/test_arcadedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,36 @@ def test_psycopg2_with_positional_parameterized_query():
assert 'Stout' in beer
finally:
conn.close()


def test_psycopg2_cypher_with_array_parameter_in_clause():
"""Test Cypher query with array parameter using IN clause - reproduces the ClassCastException issue"""
params = get_connection_params(arcadedb)
conn = psycopg.connect(**params)
conn.autocommit = True

try:
with conn.cursor() as cursor:
# Create test vertices first
cursor.execute('{cypher} CREATE (n:CHUNK {text: "chunk1"}) RETURN ID(n)')
rid1 = cursor.fetchone()[0]
cursor.execute('{cypher} CREATE (n:CHUNK {text: "chunk2"}) RETURN ID(n)')
rid2 = cursor.fetchone()[0]
cursor.execute('{cypher} CREATE (n:CHUNK {text: "chunk3"}) RETURN ID(n)')
rid3 = cursor.fetchone()[0]

# Now query with IN clause using array parameter
rids_list = [rid1, rid2, rid3]
query_params = {'ids': rids_list}
cursor.execute('{cypher} MATCH (n:CHUNK) WHERE ID(n) IN %(ids)s RETURN n.text as text, ID(n) as id', query_params)

results = cursor.fetchall()
assert len(results) == 3

# Verify we got all three chunks
texts = [r[0] for r in results]
assert 'chunk1' in texts
assert 'chunk2' in texts
assert 'chunk3' in texts
finally:
conn.close()
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,11 @@ public static Object deserialize(final long code, final int formatCode, final by
private static Object deserializeText(final long code, final byte[] valueAsBytes) {
String str = new String(valueAsBytes, DatabaseFactory.getDefaultCharset());
if (code == 0) { // UNSPECIFIED
// Try to detect if this is a PostgreSQL array format
if (str.startsWith("{") && str.endsWith("}")) {
// Parse as an array using the TEXT array parser
return parseArrayFromString(str, s -> s);
}
return str;
}

Expand Down
41 changes: 41 additions & 0 deletions postgresw/src/test/java/com/arcadedb/postgres/PostgresWJdbcIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -656,4 +656,45 @@ void createVertexCypherQueryParams() throws Exception {
}
}
}

@Disabled("Pending fix verification")
@Test
void testCypherWithArrayParameterInClause() throws Exception {
try (var conn = getConnection()) {
try (var st = conn.createStatement()) {
st.execute("create vertex type CHUNK");
// Create test vertices directly
st.execute("{cypher} CREATE (n:CHUNK {text: 'chunk1'})");
st.execute("{cypher} CREATE (n:CHUNK {text: 'chunk2'})");
st.execute("{cypher} CREATE (n:CHUNK {text: 'chunk3'})");
}

// Get all RIDs
String[] rids = new String[3];
try (var st = conn.createStatement()) {
try (var rs = st.executeQuery("{cypher} MATCH (n:CHUNK) RETURN ID(n) ORDER BY n.text")) {
int idx = 0;
while (rs.next() && idx < 3) {
rids[idx++] = rs.getString(1);
}
}
}

// Now query with IN clause using array parameter - this should reproduce the ClassCastException
try (var pst = conn.prepareStatement("{cypher} MATCH (n:CHUNK) WHERE ID(n) IN ? RETURN n.text as text ORDER BY n.text")) {
Array array = conn.createArrayOf("text", rids);
pst.setArray(1, array);

try (var rs = pst.executeQuery()) {
assertThat(rs.next()).isTrue();
assertThat(rs.getString("text")).isEqualTo("chunk1");
assertThat(rs.next()).isTrue();
assertThat(rs.getString("text")).isEqualTo("chunk2");
assertThat(rs.next()).isTrue();
assertThat(rs.getString("text")).isEqualTo("chunk3");
assertThat(rs.next()).isFalse();
}
}
}
}
}
Loading