Skip to content

Commit 1ec8344

Browse files
committed
tests: add unit test for sql query
1 parent 5a52078 commit 1ec8344

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

store/postgres/src/relational/query_tests.rs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ use std::{collections::BTreeSet, sync::Arc};
22

33
use diesel::{debug_query, pg::Pg};
44
use graph::{
5+
data_source::CausalityRegion,
56
prelude::{r, serde_json as json, DeploymentHash, EntityFilter},
67
schema::InputSchema,
78
};
89

910
use crate::{
11+
block_range::BoundSide,
1012
layout_for_tests::{make_dummy_site, Namespace},
1113
relational::{Catalog, ColumnType, Layout},
12-
relational_queries::FromColumnValue,
14+
relational_queries::{FindRangeQuery, FromColumnValue},
1315
};
1416

1517
use crate::relational_queries::Filter;
@@ -86,3 +88,112 @@ fn prefix() {
8688
let filter = EntityFilter::In("address".to_string(), vec!["0xbeef".into()]);
8789
filter_contains(filter, r#"substring(c."address", 1, 64) in ($1)"#);
8890
}
91+
92+
#[test]
93+
fn find_range_query_id_type_casting() {
94+
let string_schema = "
95+
type StringEntity @entity {
96+
id: String!,
97+
name: String
98+
}";
99+
100+
let bytes_schema = "
101+
type BytesEntity @entity {
102+
id: Bytes!,
103+
address: Bytes
104+
}";
105+
106+
let int8_schema = "
107+
type Int8Entity @entity {
108+
id: Int8!,
109+
value: Int8
110+
}";
111+
112+
let string_layout = test_layout(string_schema);
113+
let bytes_layout = test_layout(bytes_schema);
114+
let int8_layout = test_layout(int8_schema);
115+
116+
let string_table = string_layout
117+
.table_for_entity(
118+
&string_layout
119+
.input_schema
120+
.entity_type("StringEntity")
121+
.unwrap(),
122+
)
123+
.unwrap();
124+
let bytes_table = bytes_layout
125+
.table_for_entity(
126+
&bytes_layout
127+
.input_schema
128+
.entity_type("BytesEntity")
129+
.unwrap(),
130+
)
131+
.unwrap();
132+
let int8_table = int8_layout
133+
.table_for_entity(&int8_layout.input_schema.entity_type("Int8Entity").unwrap())
134+
.unwrap();
135+
136+
let causality_region = CausalityRegion::ONCHAIN;
137+
let bound_side = BoundSide::Lower;
138+
let block_range = 100..200;
139+
140+
test_id_type_casting(
141+
string_table.as_ref(),
142+
"id::bytea",
143+
"String ID should be cast to bytea",
144+
);
145+
test_id_type_casting(bytes_table.as_ref(), "id", "Bytes ID should remain as id");
146+
test_id_type_casting(
147+
int8_table.as_ref(),
148+
"id::text::bytea",
149+
"Int8 ID should be cast to text then bytea",
150+
);
151+
152+
let tables = vec![
153+
string_table.as_ref(),
154+
bytes_table.as_ref(),
155+
int8_table.as_ref(),
156+
];
157+
let query = FindRangeQuery::new(&tables, causality_region, bound_side, block_range);
158+
let sql = debug_query::<Pg, _>(&query).to_string();
159+
160+
assert!(
161+
sql.contains("id::bytea"),
162+
"String entity ID casting should be present in UNION query"
163+
);
164+
assert!(
165+
sql.contains("id as id"),
166+
"Bytes entity ID should be present in UNION query"
167+
);
168+
assert!(
169+
sql.contains("id::text::bytea"),
170+
"Int8 entity ID casting should be present in UNION query"
171+
);
172+
173+
assert!(
174+
sql.contains("union all"),
175+
"Multiple tables should generate UNION ALL queries"
176+
);
177+
assert!(
178+
sql.contains("order by block_number, entity, id"),
179+
"Query should end with proper ordering"
180+
);
181+
}
182+
183+
fn test_id_type_casting(table: &crate::relational::Table, expected_cast: &str, test_name: &str) {
184+
let causality_region = CausalityRegion::ONCHAIN;
185+
let bound_side = BoundSide::Lower;
186+
let block_range = 100..200;
187+
188+
let tables = vec![table];
189+
let query = FindRangeQuery::new(&tables, causality_region, bound_side, block_range);
190+
let sql = debug_query::<Pg, _>(&query).to_string();
191+
192+
assert!(
193+
sql.contains(expected_cast),
194+
"{}: Expected '{}' in SQL, got: {}",
195+
test_name,
196+
expected_cast,
197+
sql
198+
);
199+
}

0 commit comments

Comments
 (0)