Life-saving little things
Postgresql is without a doubt a great DBMS. It has extensive capabilities, excellent documentation, and with all this is free. However, there is always something that the user will not miss. And in postgresql this is easily fixed, because it allows you to create functions in languages for every taste, whether it be Plpgsql, Perl or even Java.
I will give an example. I always lacked a function that gets the DDL of the selected table. In oracle, for example, you can use the dbms_metadata package to do this. But in postgresql for some reason there is no analogue. That is, you can certainly use pgdump, but this is already a bit different, I would like to have a db function. And so on, I think everyone will find several such small “Wishlist”.
In any of my databases, I create in the “public” scheme a certain set of such functions that make my life easier. In this topic I want to share them. I invite everyone to share their experiences in the comments.
It is not always convenient to work with an array, often there is a desire to “select from an array with a SELECT”. In postgresql, this is possible. It is used like this: Do not scold for an example, at two in the morning nothing smarter comes to mind :).
Just what I talked about at the beginning of the topic. This is the full version of the function, it can be greatly reduced in volume by removing parameters that you will not use. For example, like this:
Actually there is 1000 and one way to encode / decode url. My method is suitable only for a small circle of tasks. Some kind of auxiliary request or something like that.
Surely not the best solution, but, nevertheless, tested and working. Used for example like this:
That's it, the inspiration for today is over). Again I urge everyone to share their experiences that make life easier. I will be glad to any comments / comments on my decisions.
I will give an example. I always lacked a function that gets the DDL of the selected table. In oracle, for example, you can use the dbms_metadata package to do this. But in postgresql for some reason there is no analogue. That is, you can certainly use pgdump, but this is already a bit different, I would like to have a db function. And so on, I think everyone will find several such small “Wishlist”.
In any of my databases, I create in the “public” scheme a certain set of such functions that make my life easier. In this topic I want to share them. I invite everyone to share their experiences in the comments.
Array to table
It is not always convenient to work with an array, often there is a desire to “select from an array with a SELECT”. In postgresql, this is possible. It is used like this: Do not scold for an example, at two in the morning nothing smarter comes to mind :).
CREATE OR REPLACE FUNCTION explode_array(IN in_array anyarray)
RETURNS SETOF anyelement AS
$$
SELECT ($1)[s] from generate_series(1,array_upper($1, 1)) as s;
$$ LANGUAGE 'sql' IMMUTABLE;
SELECT num FROM explode_array('{1,2,3}'::INTEGER[]) num WHERE num = 2;
Getting DDL tables
Just what I talked about at the beginning of the topic. This is the full version of the function, it can be greatly reduced in volume by removing parameters that you will not use. For example, like this:
CREATE OR REPLACE FUNCTION extract_ddl(IN table_name text, IN db_name text,
IN host text, IN user_name text)
RETURNS text AS
$$
my $table_name = $_[0];
my $db_name = $_[1];
my $host = $_[2];
my $user_name = $_[3];
my $str = `pg_dump -s -t $table_name -h $host -U $user_name $db_name`;
return $str;
$$ LANGUAGE 'plperlu';
CREATE OR REPLACE FUNCTION extract_ddl(IN table_name text, IN db_name text)
RETURNS text AS
$$
my $table_name = $_[0];
my $db_name = $_[1];
my $str = `pg_dump -s -t $table_name $db_name`;
return $str;
$$ LANGUAGE 'plperlu';
urldecode / urlencode
Actually there is 1000 and one way to encode / decode url. My method is suitable only for a small circle of tasks. Some kind of auxiliary request or something like that.
CREATE OR REPLACE FUNCTION urlencode (IN url text, IN encoding text)
RETURNS text AS
$$
use URI::Escape;
use Encode;
my $url=$_[0];
my $encoding=$_[1];
return uri_escape(encode($encoding, $url));
$$ LANGUAGE plperlu IMMUTABLE;
CREATE OR REPLACE FUNCTION urldecode (IN url text, IN encoding text)
RETURNS text AS
$$
use Encode;
use URI::Escape;
my $str = uri_unescape($_[0]);
my $encoding = $_[1];
eval {
$str = decode($encoding, $str);
};
if ($@){
return $str;
};
return $str;
$$ LANGUAGE plperlu IMMUTABLE;
Get domain name from URL
Surely not the best solution, but, nevertheless, tested and working. Used for example like this:
CREATE OR REPLACE FUNCTION extract_domain(IN url text, IN domain_level INTEGER)
RETURNS text AS
$$
DECLARE
v_domain_full text;
v_domain text;
v_matches text[];
v_level INTEGER := 1;
v_url_levels INTEGER := 0;
rec record;
BEGIN
SELECT regexp_matches(lower(url), E'https?://(www\\.)?([-a-zA-Z0-9.]*\\.[a-z]{2,5})', 'gi') INTO v_matches LIMIT 1;
IF v_matches IS NULL OR v_matches[2] IS NULL THEN
RETURN NULL;
END IF;
v_domain_full := v_matches[2];
v_matches := regexp_split_to_array(v_domain_full, E'\\.');
SELECT count(*) INTO v_url_levels FROM regexp_split_to_table(v_domain_full, E'\\.');
IF v_url_levels = domain_level THEN
RETURN v_domain_full;
END IF;
IF v_url_levels < domain_level THEN
RETURN NULL;
END IF;
v_domain := v_matches[v_url_levels];
IF (domain_level > 1) THEN
FOR i IN 1..domain_level-1 LOOP
v_domain := v_matches[v_url_levels - i] || '.' || v_domain;
END LOOP;
END IF;
RETURN v_domain;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;
SELECT * FROM extract_domain('http://www.google.com/search?q=postgresql+is+great', 2);
Result:
-----------------
google.com
Fin
That's it, the inspiration for today is over). Again I urge everyone to share their experiences that make life easier. I will be glad to any comments / comments on my decisions.