Skip to content

Commit c3ba1ab

Browse files
committed
Fix panic caused by unknown cursor columns when executing NullRow command. Fixes launchbadge#1249
1 parent f08bdf1 commit c3ba1ab

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

sqlx-core/src/sqlite/connection/explain.rs

+61-1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,50 @@ pub(super) fn explain(
112112
// Nullable columns
113113
let mut n = HashMap::<i64, bool>::with_capacity(6);
114114

115+
let table_block_columns: Vec<(i64, i64, String)> = execute::iter(
116+
conn,
117+
"SELECT s.rootpage, col.cid as colnum, col.type
118+
FROM sqlite_schema s
119+
JOIN pragma_table_info(s.name) AS col
120+
WHERE s.type = 'table'",
121+
None,
122+
false,
123+
)?
124+
.filter_map(|res| res.map(|either| either.right()).transpose())
125+
.map(|row| FromRow::from_row(&row?))
126+
.collect::<Result<Vec<_>, Error>>()?;
127+
128+
let index_block_columns: Vec<(i64, i64, String)> = execute::iter(
129+
conn,
130+
"SELECT s.rootpage, idx.seqno as colnum, col.type
131+
FROM sqlite_schema s
132+
JOIN pragma_index_info(s.name) AS idx
133+
LEFT JOIN pragma_table_info(s.tbl_name) as col
134+
ON col.cid = idx.cid
135+
WHERE s.type = 'index'",
136+
None,
137+
false,
138+
)?
139+
.filter_map(|res| res.map(|either| either.right()).transpose())
140+
.map(|row| FromRow::from_row(&row?))
141+
.collect::<Result<Vec<_>, Error>>()?;
142+
143+
let mut cursor_row_info: HashMap<i64, HashMap<i64, DataType>> = HashMap::new();
144+
for (block, colnum, datatype) in table_block_columns {
145+
let row_info = cursor_row_info.entry(block).or_default();
146+
row_info.insert(
147+
colnum,
148+
datatype.parse().unwrap_or(DataType::Null),
149+
);
150+
}
151+
for (block, colnum, datatype) in index_block_columns {
152+
let row_info = cursor_row_info.entry(block).or_default();
153+
row_info.insert(
154+
colnum,
155+
datatype.parse().unwrap_or(DataType::Null),
156+
);
157+
}
158+
115159
let program: Vec<(i64, String, i64, i64, i64, Vec<u8>)> =
116160
execute::iter(conn, &format!("EXPLAIN {}", query), None, false)?
117161
.filter_map(|res| res.map(|either| either.right()).transpose())
@@ -190,7 +234,23 @@ pub(super) fn explain(
190234

191235
OP_OPEN_READ | OP_OPEN_WRITE | OP_OPEN_EPHEMERAL | OP_OPEN_AUTOINDEX => {
192236
//Create a new pointer which is referenced by p1
193-
p.insert(p1, HashMap::with_capacity(6));
237+
238+
//Create a new pointer which is referenced by p1, take column metadata from db schema if found
239+
if p3 == 0 {
240+
if let Some(table_columns) = cursor_row_info.get(&p2) {
241+
p.insert(
242+
p1,
243+
table_columns
244+
.iter()
245+
.map(|(&colnum, &datatype)| (colnum, datatype))
246+
.collect(),
247+
);
248+
} else {
249+
p.insert(p1, HashMap::with_capacity(6));
250+
}
251+
} else {
252+
p.insert(p1, HashMap::with_capacity(6));
253+
}
194254
}
195255

196256
OP_VARIABLE => {

0 commit comments

Comments
 (0)