Skip to content

Commit

Permalink
Use UNION ALL instead of UNION in nullable check (#3605)
Browse files Browse the repository at this point in the history
  • Loading branch information
Suficio authored Nov 26, 2024
1 parent d4ae6ff commit 8031460
Showing 1 changed file with 34 additions and 15 deletions.
49 changes: 34 additions & 15 deletions sqlx-postgres/src/connection/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,26 +448,45 @@ WHERE rngtypid = $1
// This will include columns that don't have a `relation_id` (are not from a table);
// assuming those are a minority of columns, it's less code to _not_ work around it
// and just let Postgres return `NULL`.
let mut nullable_query = QueryBuilder::new("SELECT NOT pg_attribute.attnotnull FROM ( ");

nullable_query.push_values(meta.columns.iter().zip(0i32..), |mut tuple, (column, i)| {
// ({i}::int4, {column.relation_id}::int4, {column.relation_attribute_no}::int2)
tuple.push_bind(i).push_unseparated("::int4");
tuple
.push_bind(column.relation_id)
.push_unseparated("::int4");
tuple
.push_bind(column.relation_attribute_no)
.push_unseparated("::int2");
});
//
// Use `UNION ALL` syntax instead of `VALUES` due to frequent lack of
// support for `VALUES` in pgwire supported databases.
let mut nullable_query = QueryBuilder::new("SELECT NOT attnotnull FROM ( ");
let mut separated = nullable_query.separated("UNION ALL ");

let mut column_iter = meta.columns.iter().zip(0i32..);
if let Some((column, i)) = column_iter.next() {
separated.push("( SELECT ");
separated
.push_bind_unseparated(i)
.push_unseparated("::int4 AS idx, ");
separated
.push_bind_unseparated(column.relation_id)
.push_unseparated("::int4 AS table_id, ");
separated
.push_bind_unseparated(column.relation_attribute_no)
.push_unseparated("::int2 AS col_idx ) ");
}

for (column, i) in column_iter {
separated.push("( SELECT ");
separated
.push_bind_unseparated(i)
.push_unseparated("::int4, ");
separated
.push_bind_unseparated(column.relation_id)
.push_unseparated("::int4, ");
separated
.push_bind_unseparated(column.relation_attribute_no)
.push_unseparated("::int2 ) ");
}

nullable_query.push(
") as col(idx, table_id, col_idx) \
LEFT JOIN pg_catalog.pg_attribute \
") AS col LEFT JOIN pg_catalog.pg_attribute \
ON table_id IS NOT NULL \
AND attrelid = table_id \
AND attnum = col_idx \
ORDER BY col.idx",
ORDER BY idx",
);

let mut nullables: Vec<Option<bool>> = nullable_query
Expand Down

0 comments on commit 8031460

Please sign in to comment.