Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add plpgsql stored proc to compare debian versions
- Loading branch information
Showing
1 changed file
with
125 additions
and
0 deletions.
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
db/migrate/20180601160100_add_deb_version_cmp_function_to_db.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
class AddDebVersionCmpFunctionToDb < ActiveRecord::Migration[4.2] | ||
# Implementation of version compare for debian packages | ||
# Reference: http://man7.org/linux/man-pages/man5/deb-version.5.html | ||
def self.up | ||
unless connection.adapter_name.downcase.include?('sqlite') | ||
execute " | ||
CREATE OR REPLACE FUNCTION deb_version_cmp_num(_left text, _right text) RETURNS integer AS $$ | ||
DECLARE | ||
lint integer := 0; | ||
rint integer := 0; | ||
BEGIN | ||
IF _left != '' THEN | ||
lint := _left AS integer; | ||
END IF; | ||
IF _right != '' THEN | ||
rint := _right AS integer; | ||
END IF; | ||
IF lint < rint THEN | ||
RETURN -1; | ||
ELSEIF lint > rint THEN | ||
RETURN 1; | ||
ELSE | ||
RETURN 0; | ||
END IF; | ||
END; | ||
$$ IMMUTABLE STRICT LANGUAGE plpgsql; | ||
CREATE OR REPLACE FUNCTION deb_version_cmp_al(_left text, _right text) | ||
RETURNS integer | ||
AS $$ | ||
DECLARE | ||
lpair text ARRAY[2]; | ||
rpair text ARRAY[2]; | ||
BEGIN | ||
lpair := ARRAY['', _left]; | ||
rpair := ARRAY['', _right]; | ||
LOOP | ||
IF lpair[2] = '' AND rpair[2] = '' THEN | ||
return 0; | ||
END IF; | ||
lpair := regexp_matches(lpair[2], '(.?)(.*)'); | ||
rpair := regexp_matches(rpair[2], '(.?)(.*)'); | ||
IF lpair[1] = rpair[1] THEN | ||
CONTINUE; | ||
END IF; | ||
IF lpair[1] = '~' THEN | ||
RETURN -1; | ||
END IF; | ||
IF rpair[1] = '~' THEN | ||
RETURN 1; | ||
END IF; | ||
IF lpair[1] = '' THEN | ||
RETURN -1; | ||
END IF; | ||
IF rpair[1] = '' THEN | ||
RETURN 1; | ||
END IF; | ||
IF lpair[1] SIMILAR TO '[a-zA-Z]' THEN | ||
IF rpair[1] SIMILAR TO '[a-zA-Z]' AND ascii(lpair[1]) > ascii(rpair[1]) THEN | ||
RETURN 1; | ||
END IF; | ||
RETURN -1; | ||
END IF; | ||
IF rpair[1] SIMILAR TO '[a-zA-Z]' THEN | ||
RETURN 1; | ||
END IF; | ||
IF ascii(lpair[1]) < ascii(rpair[1]) THEN | ||
RETURN -1; | ||
END IF; | ||
RETURN 1; | ||
END LOOP; | ||
END; | ||
$$ IMMUTABLE STRICT LANGUAGE plpgsql; | ||
CREATE OR REPLACE FUNCTION deb_version_cmp(_left text, _right text) | ||
RETURNS integer | ||
AS $$ | ||
DECLARE | ||
lpair text ARRAY[2]; | ||
rpair text ARRAY[2]; | ||
res integer; | ||
BEGIN | ||
lpair := ARRAY['', _left]; | ||
rpair := ARRAY['', _right]; | ||
LOOP | ||
IF lpair[2] = '' AND rpair[2] = '' THEN | ||
return 0; | ||
END IF; | ||
lpair := regexp_matches(lpair[2], '([^\\d]*)(.*)'); | ||
rpair := regexp_matches(rpair[2], '([^\\d]*)(.*)'); | ||
res := deb_version_cmp_al(lpair[1], rpair[1]); | ||
IF res != 0 THEN | ||
RETURN res; | ||
END IF; | ||
lpair := regexp_matches(lpair[2], '(\\d*)(.*)'); | ||
rpair := regexp_matches(rpair[2], '(\\d*)(.*)'); | ||
res := deb_version_cmp_num(lpair[1], rpair[1]); | ||
IF res != 0 THEN | ||
RETURN res; | ||
END IF; | ||
END LOOP; | ||
END | ||
$$ IMMUTABLE STRICT LANGUAGE plpgsql; | ||
" | ||
end | ||
end | ||
|
||
def self.down | ||
unless connection.adapter_name.downcase.include?('sqlite') | ||
execute " | ||
DROP FUNCTION deb_version_cmp(text, text) CASCADE; | ||
DROP FUNCTION deb_version_cmp_al(text, text) CASCADE; | ||
DROP FUNCTION deb_version_cmp_num(text, text) CASCADE; | ||
" | ||
end | ||
end | ||
end |