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
4 changes: 3 additions & 1 deletion src/expr/src/relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,9 @@ impl MirRelationExpr {
.column_types
.iter()
.zip_eq(typ.column_types.iter())
.all(|(t1, t2)| t1.scalar_type.base_eq(&t2.scalar_type))
.all(|(t1, t2)| t1
.scalar_type
.base_eq_or_repr_eq_for_assertion(&t2.scalar_type))
);
}
let mut typ = typ.unwrap_or_else(|| self.typ());
Expand Down
8 changes: 7 additions & 1 deletion src/repr/src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3299,7 +3299,13 @@ impl SqlScalarType {
}

::tracing::error!("repr type error: base_eq failed for {self:?} and {other:?}");
ReprScalarType::from(self) == ReprScalarType::from(other)
// SqlScalarType::base_eq does not consider nullability at all, but `ReprScalarType::eq` does
// To reconcile these differences, we check "compatibility", i.e., if we can union the types wthout error.
// Since ReprScalarType::union is a glorified nullability compositor, a successful union means the types
// are equal (modulo nullability)
ReprScalarType::from(self)
.union(&ReprScalarType::from(other))
.is_ok()
}

// Determines equality among scalar types that ignores any custom OIDs or
Expand Down
134 changes: 134 additions & 0 deletions test/sqllogictest/transform/normalize_lets.slt
Original file line number Diff line number Diff line change
Expand Up @@ -628,3 +628,137 @@ Used Indexes:
Target cluster: quickstart

EOF

## regression test from sqlsmith that crashed an assertion in normalize_lets

statement ok
EXPLAIN OPTIMIZED PLAN FOR select
mz_internal.mz_session_id() as c0,
pg_catalog.jsonb_build_array() as c1,
((((0::uint4) & (0::uint4)) # (cast(coalesce(2::uint4,
case when false then null::uint4 else null::uint4 end
) as uint4))) * (mz_catalog.seahash(
CAST(case when ((0::uint8) <= (null::uint8))
and (true) then pg_catalog.digest(
CAST(1::text as text),
CAST(2::text as text)) else pg_catalog.digest(
CAST(1::text as text),
CAST(2::text as text)) end
as bytea)))) # (mz_catalog.seahash(
CAST(cast(coalesce(pg_catalog.sha512(
CAST(pg_catalog.sha384(
CAST(cast('\xDEADBEEF' as bytea) as bytea)) as bytea)),
cast(nullif(pg_catalog.hmac(
CAST(cast('\xDEADBEEF' as bytea) as bytea),
CAST(cast('\xDEADBEEF' as bytea) as bytea),
CAST(1::text as text)),
cast('\xFFFFFF' as bytea)) as bytea)) as bytea) as bytea))) as c2,
pg_catalog.makeaclitem(
CAST(mz_internal.aclitem_grantee(
CAST(cast(null as aclitem) as aclitem)) as oid),
CAST(mz_internal.aclitem_grantor(
CAST(case when 87 is not NULL then pg_catalog.makeaclitem(
CAST(mz_internal.aclitem_grantor(
CAST(cast(null as aclitem) as aclitem)) as oid),
CAST(null::oid as oid),
CAST(case when false then null::text else null::text end
as text),
CAST(true as bool)) else pg_catalog.makeaclitem(
CAST(mz_internal.aclitem_grantor(
CAST(cast(null as aclitem) as aclitem)) as oid),
CAST(null::oid as oid),
CAST(case when false then null::text else null::text end
as text),
CAST(true as bool)) end
as aclitem)) as oid),
CAST(case when ((case when (true)
or (false) then 1::text else 1::text end
) || (pg_catalog.chr(
CAST(68 as int4)))) <= (pg_catalog.session_user()) then cast(nullif((pg_catalog.obj_description(
CAST(null::oid as oid),
CAST(1::text as text))) || (case when (TIME '00:00:00') >= (TIME '01:23:45') then null::text else null::text end
),
pg_catalog.current_schema()) as text) else cast(nullif((pg_catalog.obj_description(
CAST(null::oid as oid),
CAST(1::text as text))) || (case when (TIME '00:00:00') >= (TIME '01:23:45') then null::text else null::text end
),
pg_catalog.current_schema()) as text) end
as text),
CAST(case when (cast(coalesce((null::uint4) | (2::uint4),
cast(nullif(0::uint4,
null::uint4) as uint4)) as uint4)) >= (null::uint4) then pg_catalog.pg_has_role(
CAST(cast(0 as oid) as oid),
CAST(cast(coalesce(case when ('{}'::jsonb) = ('[]'::jsonb) then 1::oid else 1::oid end
,
1::oid) as oid) as oid),
CAST(pg_catalog.current_database() as text)) else pg_catalog.pg_has_role(
CAST(cast(0 as oid) as oid),
CAST(cast(coalesce(case when ('{}'::jsonb) = ('[]'::jsonb) then 1::oid else 1::oid end
,
1::oid) as oid) as oid),
CAST(pg_catalog.current_database() as text)) end
as bool)) as c3,
pg_catalog.pg_is_in_recovery() as c4,
mz_catalog.mz_now() as c5,
pg_catalog.timezone(
CAST(mz_catalog.mz_version() as text),
CAST(pg_catalog.current_timestamp() as timestamptz)) as c6,
pg_catalog.reverse(
CAST((mz_catalog.mz_version()) || (1::text) as text)) as c7
from
(select
case when false then mz_internal.mz_role_oid_memberships() else mz_internal.mz_role_oid_memberships() end
as c0,
mz_internal.mz_role_oid_memberships() as c1,
pg_catalog.current_database() as c2,
mz_internal.mz_name_rank(
CAST(pg_catalog.version() as text),
CAST(array['a', 'b', null, '']::text[] as _text),
CAST(case when (cast(0 as bpchar)) > (cast(0 as bpchar)) then 1::text else 1::text end
as text),
CAST(1::text as text)) as c3,
mz_catalog.mz_uptime() as c4,
mz_internal.mz_role_oid_memberships() as c5,
case when false then 58 else 58 end
as c6,
(case when ((2::int8) <> (-9223372036854775808::int8))
or ((-32768::int2) = (-32768::int2)) then 0::uint8 else 0::uint8 end
) / (0::uint8) as c7,
mz_internal.mz_role_oid_memberships() as c8,
(cast(coalesce('inf'::float4,
'nan'::float4) as float4)) - (case when ((67) = (19))
or (52 is NULL) then 'inf'::float4 else 'inf'::float4 end
) as c9,
mz_catalog.mz_uptime() as c10
from
(select
18 as c0,
50 as c1
from
(select
73 as c0,
58 as c1,
24 as c2,
32 as c3,
12 as c4
from
"mz_internal"."mz_session_history" as ref_11
where true) as subq_8
where false) as subq_9
where (array[null, null]) > (pg_catalog.regexp_split_to_array(
CAST(('{"1":2,"3":4}'::jsonb) ->> (9223372036854775807::int8) as text),
CAST(cast(0 as text) as text),
CAST(pg_catalog.session_user() as text)))) as subq_10
where (mz_internal.aclitem_grantee(
CAST(cast(null as aclitem) as aclitem))) <= (mz_internal.aclitem_grantor(
CAST(pg_catalog.makeaclitem(
CAST(case when (cast(coalesce(cast('\xDEADBEEF' as bytea),
cast('\xDEADBEEF' as bytea)) as bytea)) >= (cast('\xDEADBEEF' as bytea)) then case when ((cast('\xFFFFFF' as bytea)) >= (cast('\xFFFFFF' as bytea)))
or ((61) >= (6)) then 1::oid else 1::oid end
else case when ((cast('\xFFFFFF' as bytea)) >= (cast('\xFFFFFF' as bytea)))
or ((61) >= (6)) then 1::oid else 1::oid end
end
as oid),
CAST(cast(0 as oid) as oid),
CAST(pg_catalog.session_user() as text),
CAST(mz_internal.is_rbac_enabled() as bool)) as aclitem)));