Skip to content

Commit 1be11a3

Browse files
committed
test(sqlx): add FK enforcement behavior tests
Extends foreign_key_constraint_with_encrypted test to verify FK enforcement behavior with deterministic test data. Demonstrates that: 1. FK constraints DO work with deterministic encrypted data (test framework) 2. Successfully insert child with matching parent reference 3. Correctly reject child with non-existent parent reference Documents PRODUCTION LIMITATION: In real-world usage with non-deterministic encryption, FK constraints don't provide meaningful referential integrity because each encryption of the same plaintext produces different ciphertext. Adds 4 new assertions testing FK enforcement behavior. Addresses FINAL_CODE_REVIEW.md recommendation #4 (P2).
1 parent fab6a39 commit 1be11a3

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

tests/sqlx/tests/constraint_tests.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,66 @@ async fn foreign_key_constraint_with_encrypted(pool: PgPool) -> Result<()> {
163163

164164
assert!(fk_exists, "Foreign key constraint should exist");
165165

166+
// TEST FK ENFORCEMENT BEHAVIOR:
167+
// With deterministic test data, FK constraints DO enforce referential integrity
168+
// because we can use the exact same encrypted bytes.
169+
//
170+
// PRODUCTION LIMITATION: In real-world usage with non-deterministic encryption,
171+
// FK constraints don't provide meaningful referential integrity because:
172+
// 1. Each encryption of the same plaintext produces different ciphertext
173+
// 2. The FK check compares encrypted bytes, not plaintext values
174+
// 3. Two encryptions of "1" will have different bytes and won't match
175+
//
176+
// This test uses deterministic test helpers, so FKs DO work here.
177+
178+
// Insert a parent record with encrypted value for plaintext "1"
179+
sqlx::query("INSERT INTO parent (id) VALUES (create_encrypted_json(1, 'hm'))")
180+
.execute(&pool)
181+
.await?;
182+
183+
// Verify parent record exists
184+
let parent_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM parent")
185+
.fetch_one(&pool)
186+
.await?;
187+
188+
assert_eq!(parent_count, 1, "Should have 1 parent record");
189+
190+
// Successfully insert child record with FK to same deterministic value
191+
// This SUCCEEDS because create_encrypted_json(1, 'hm') returns identical bytes each time
192+
sqlx::query(
193+
"INSERT INTO child (id, parent_id) VALUES (1, create_encrypted_json(1, 'hm'))",
194+
)
195+
.execute(&pool)
196+
.await?;
197+
198+
// Verify child record was inserted
199+
let child_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM child")
200+
.fetch_one(&pool)
201+
.await?;
202+
203+
assert_eq!(
204+
child_count, 1,
205+
"Child insert should succeed with matching deterministic encrypted value"
206+
);
207+
208+
// Attempt to insert child with different encrypted value (should fail FK check)
209+
let different_insert_result = sqlx::query(
210+
"INSERT INTO child (id, parent_id) VALUES (2, create_encrypted_json(2, 'hm'))",
211+
)
212+
.execute(&pool)
213+
.await;
214+
215+
assert!(
216+
different_insert_result.is_err(),
217+
"FK constraint should reject non-existent parent reference"
218+
);
219+
220+
// Verify child count unchanged
221+
let final_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM child")
222+
.fetch_one(&pool)
223+
.await?;
224+
225+
assert_eq!(final_count, 1, "FK violation should prevent second child insert");
226+
166227
Ok(())
167228
}

0 commit comments

Comments
 (0)