Skip to content

Commit

Permalink
chore: mark fns a "immutable parallel safe"
Browse files Browse the repository at this point in the history
  • Loading branch information
ctron committed Sep 2, 2024
1 parent 0126fae commit d0b9b43
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 0 deletions.
2 changes: 2 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ mod m0000560_alter_vulnerability_cwe_column;
mod m0000565_alter_advisory_vulnerability_cwe_column;
mod m0000570_add_import_progress;
mod m0000575_create_weakness;
mod m0000580_mark_fns;

pub struct Migrator;

Expand Down Expand Up @@ -147,6 +148,7 @@ impl MigratorTrait for Migrator {
Box::new(m0000565_alter_advisory_vulnerability_cwe_column::Migration),
Box::new(m0000570_add_import_progress::Migration),
Box::new(m0000575_create_weakness::Migration),
Box::new(m0000580_mark_fns::Migration),
]
}
}
Expand Down
153 changes: 153 additions & 0 deletions migration/src/m0000580_mark_fns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/rpmver_version_matches.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_cmp.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_version_matches.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_version_matches.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/is_numeric.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/is_numeric.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_eq.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_gt.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_gte.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_lt.sql"))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!("m0000580_mark_fns/semver_lte.sql"))
.await
.map(|_| ())?;

Ok(())
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/semver_lte.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/semver_lt.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/semver_gte.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/semver_gt.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/semver_eq.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000345_create_version_comparison_fns/is_numeric.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000475_improve_version_comparison_fns/semver_version_matches.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000475_improve_version_comparison_fns/semver_cmp.sql"
))
.await
.map(|_| ())?;

manager
.get_connection()
.execute_unprepared(include_str!(
"m0000480_create_rpmver_cmp_fns/rpmver_version_matches.sql"
))
.await
.map(|_| ())?;

Ok(())
}
}
10 changes: 10 additions & 0 deletions migration/src/m0000580_mark_fns/is_numeric.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
create or replace function is_numeric(str text)
returns bool
as
$$
begin
return str ~ e'^[0-9]+$';
end

$$
language 'plpgsql' immutable parallel safe;
53 changes: 53 additions & 0 deletions migration/src/m0000580_mark_fns/rpmver_version_matches.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

create or replace function rpmver_version_matches(version_p text, range_p version_range)
returns bool
as
$$
declare
low_end integer;
high_end integer;
begin
if range_p.low_version is not null then
low_end := rpmver_cmp(version_p, range_p.low_version);
end if;

if low_end is not null then
if range_p.low_inclusive then
if low_end < 0 then
return false;
end if;
else
if low_end <= 0 then
return false;
end if;
end if;

end if;


if range_p.high_version is not null then
high_end := rpmver_cmp(version_p, range_p.high_version);
end if;

if high_end is not null then
if range_p.high_inclusive then
if high_end > 0 then
return false;
end if;
else
if high_end >= 0 then
return false;
end if;
end if;
end if;

if low_end is null and high_end is null then
return false;
end if;

return true;

end
$$
language 'plpgsql' immutable parallel safe;

128 changes: 128 additions & 0 deletions migration/src/m0000580_mark_fns/semver_cmp.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@

create or replace function semver_cmp(left_p text, right_p text)
returns integer
as
$$
declare
left_parts text[];
right_parts text[];

left_major bigint;
left_minor bigint;
left_patch bigint;
left_pre text;
left_build text;

right_major bigint;
right_minor bigint;
right_patch bigint;
right_pre text;
right_build text;

left_numeric bool;
right_numeric bool;

cur integer;

begin

raise notice 'semver_cmp % %', left_p, right_p;

left_parts = regexp_split_to_array(left_p, E'\\+');
left_build = left_parts[2];

left_parts = regexp_split_to_array(left_parts[1], E'-');
left_pre = left_parts[2];

left_parts = regexp_split_to_array(left_parts[1], E'\\.');
left_major = left_parts[1]::decimal;
left_minor = left_parts[2]::decimal;
left_patch = left_parts[3]::decimal;

right_parts = regexp_split_to_array(right_p, E'\\+');
right_build = right_parts[2];

right_parts = regexp_split_to_array(right_parts[1], E'-');
right_pre = right_parts[2];

right_parts = regexp_split_to_array(right_parts[1], E'\\.');
right_major = right_parts[1]::decimal;
right_minor = right_parts[2]::decimal;
right_patch = right_parts[3]::decimal;

if left_major > right_major then
return +1;
elsif left_major < right_major then
return -1;
end if;

if left_minor > right_minor then
return +1;
elsif left_minor < right_minor then
return -1;
end if;

if left_patch > right_patch then
return +1;
elsif left_patch < right_patch then
return -1;
end if;

if left_pre is null and right_pre is not null then
return +1;
elsif left_pre is not null and right_pre is null then
return -1;
elsif left_pre is not null and right_pre is not null then
left_parts = regexp_split_to_array(left_pre, E'\\.');
right_parts = regexp_split_to_array(right_pre, E'\\.');
-- do the hard work

cur := 0;
loop
cur := cur + 1;

left_pre := left_parts[cur];
right_pre := right_parts[cur];

if left_pre is null and right_pre is null then
return 0;
end if;

if left_pre is null and right_pre is not null then
return -1;
elsif left_pre is not null and right_pre is null then
return +1;
end if;

left_numeric := is_numeric(left_pre);
right_numeric := is_numeric(right_pre);

if left_numeric and right_numeric then
if left_pre::bigint < right_pre::bigint then
return -1;
elsif left_pre::bigint > right_pre::bigint then
return +1;
end if;
else
if left_pre < right_pre then
return -1;
elsif left_pre > right_pre then
return +1;
end if;
end if;

if cur > 10 then
exit;
end if;
end loop;
else
return 0;
end if;

return null;
exception
when others then
return null;
end
$$
language 'plpgsql' immutable parallel safe;
12 changes: 12 additions & 0 deletions migration/src/m0000580_mark_fns/semver_eq.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
create or replace function semver_eq(left_p text, right_p text)
returns bool
as
$$
declare
cmp integer;
begin
cmp := semver_cmp(left_p, right_p);
return cmp = 0;
end
$$
language 'plpgsql';
12 changes: 12 additions & 0 deletions migration/src/m0000580_mark_fns/semver_gt.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
create or replace function semver_gt(left_p text, right_p text)
returns bool
as
$$
declare
cmp integer;
begin
cmp := semver_cmp(left_p, right_p);
return cmp > 0;
end
$$
language 'plpgsql' immutable parallel safe;
Loading

0 comments on commit d0b9b43

Please sign in to comment.