dynamic SQL parameters in PL/PgSQL functions
It pays to read documentation.
From PostgreSQL 8.3 to 8.4 there was one interesting addon for plpgsql: ability to pass parameter values directly into EXECUTE.
Of course depesz wrote about it. And I did read it; But still (by routine) I was using something like:
sql_query := 'SELECT foo FROM bar JOIN baz USING (barbaz) WHERE baz.id = ANY (__PARAM__::integer[])';
sql_query := replace(sql_query, '__PARAM__', quote_nullable(my_param);
EXECUTE sql_query INTO my_foos;
While it can be written in more elegant and error-prone way:
EXECUTE 'SELECT foo FROM bar JOIN baz USING (barbaz) WHERE baz.id = ANY ($1)'
INTO my_foos
USING my_param;
postgres schemagrep function
From time to time, I need to "grep" database schema to locate some database objects.
One possibility is to dump the whole schema to file (pg_dump -s DBNAME) and use your text editor to browse it. It is quite handy and I actually use it a lot.
But sometimes, it is more convenient to have this "grep-like" possibility directly from psql.
So... here it is, the "schemagrep" function.
Please note that argument for this function is a regex pattern, so you can look for almost everything.
The search is case-insensitive.
begin;
create or replace function schemagrep_relkind( "char" ) returns text as $$
select case $1
when 'r' then 'TABLE'
when 'i' then 'INDEX'
when 'S' then 'SEQUENCE'
when 'v' then 'VIEW'
when 'c' then 'COMPOSITE TYPE'
when 't' then 'TOAST TABLE'
end
$$ language sql immutable strict;
drop function if exists schemagrep( text );
create function schemagrep( text ) returns table(
schema name,
object_name name,
match_type text,
psql_hint text
) as $$
select x.*, case when x.match_type ~ 'FUNCTION' then E'\\df+ ' when x.match_type ~ 'COMMENT' then E'\\d+ ' else E'\\d ' end || nspname || '.' || relname
from (
select n.nspname, c.relname, schemagrep_relkind(c.relkind) || ' NAME' as match_type
from pg_class c, pg_namespace n where c.relname ~* $1 and c.relnamespace = n.oid
union all
select distinct n.nspname, c.relname, schemagrep_relkind(c.relkind) || ' ATTRIBUTE'
from pg_class c, pg_attribute a, pg_namespace n where a.attrelid = c.oid and c.relkind <> 'v' and a.attname ~* $1 and c.relnamespace = n.oid
union all
select n.nspname, proname, 'FUNCTION DEFINITION'
from pg_proc, pg_namespace n where prosrc ~* $1 and pronamespace = n.oid
union all
select schemaname, viewname, 'VIEW DEFINITION'
from pg_views where definition ~* $1
union all
select n.nspname, relname, 'CLASS CONSTRAINT'
from pg_class c, pg_constraint cx, pg_namespace n where cx.conrelid = c.oid and cx.consrc ~* $1 and relnamespace = n.oid
union all
select distinct n.nspname, c.relname, 'COMMENT'
from pg_class c, pg_description d, pg_namespace n where d.objoid = c.oid and d.description ~* $1 and c.relnamespace = n.oid
) x
$$ language sql stable strict;
grant execute on function schemagrep(text) to public;
commit;
Test it by running
SELECT * FROM schemagrep( 'anything' );
For me, it works like this:
testdb=# select * from schemagrep('account');
schema | object_name | match_type | psql_hint
--------+-----------------------+---------------------+----------------------------------
public | pgbench_accounts | TABLE NAME | \d public.pgbench_accounts
public | pgbench_accounts_pkey | INDEX NAME | \d public.pgbench_accounts_pkey
public | sp_acc_createaccount | FUNCTION DEFINITION | \df+ public.sp_acc_createaccount
(3 rows)
That's it! Of course the function can be extended or modified to your needs, because it's in pure SQL :-)
iterate over a table in PostgreSQL vs SAS
I have struggled how to achieve something like this in SAS.
(you can read it as pseudocode but it's real PL/PgSQL):
DO $this$
DECLARE my_table name;
BEGIN;
-- iterate over table names
FOR my_table IN SELECT nazwa FROM tabele
LOOP
sql := 'CREATE TABLE XXX_backup AS SELECT * FROM XXX';
sql := replace(sql, 'XXX', my_table);
execute sql;
END LOOP;
END;
$this$ language plpgsql;
After consulting a collegue [thx Ludwik] and exploring this helpful doc:
Performing Multiple Statements for Each Record in a SAS® Data Set, tadam:
%MACRO COPYTABLES(SCANFILE,SCANFIELD);
*get number of tables;
DATA _NULL_;
IF 0 THEN SET &SCANFILE NOBS=X;
CALL SYMPUT('RECCOUNT',X);
STOP;
RUN;
*iterate;
%DO I=1 %TO &RECCOUNT;
*get table name;
DATA _NULL_;
SET &SCANFILE (FIRSTOBS=&I);
CALL SYMPUT('TABLENAME',&SCANFIELD);
STOP;
RUN;
*copy;
DATA &TABLENAME._backup;
SET &TABLENAME;
RUN;
%END;
%MEND COPYSETS;
%COPYSETS(tabele,nazwa);
When you switch from procedural coding to macro coding, you have twist your brain upside down...
I had to read a white paper (SAS docs lacking examples) and scratch my head for a moment before writing this simple procedural loop in SAS 4GL.
Now tell me that SAS isn't weird ;-)
american dream
Hosanna! wreszcie obejrzę film widmo który ścigał mnie przez ostatnie kilka lat. Właściwie - od czasu gdy po raz pierwszy zobaczyłem Arizona Dream. [ BTW - zasadniczo jestem WYZNAWCĄ Kusturicy ]
No i właśnie teraz, w kolekcji kolegi [ misiekbest - dzięki! ] wyhaczyłem North By Northwest. I skojarzyłem że to właśnie z tego filmu pochodzi sławna scena z ucieczką przed samolotem na spalonej słońcem równinie.
Damn, jakie to amerykańskie. Dlaczego mnie tak to rusza?
Ktoś powie - to oczywiste dlaczego amerykańskie kino cię rusza. Może kilka kluczowych motywów rodem z holywood przegrywanych mediami na okrągło przez wiele lat przepaliło ci mózg?
a może po prostu COŚ w tym jest.
To COŚ to kilka podstaw w które Stany Zjednoczone kiedyś wierzyły. I które manifestują się we wzorcu kina drogi.
Świat jest wielki, a dla Ciebie znajdzie się w nim miejsce.
Życie to droga. Droga na Zachód.
Droga to wolność.
Wolność jest najważniejsza. Twoja wolność kończy się tam gdzie zaczyna się cudza krzywda.
Masz prawo do obrony wolności zawsze i wszędzie.
Czy te wartości są prawdziwe? A może to tylko sen?
W głowie kręcą mi się skojarzenia filmowe i trochę literackie.
Truposz, chyba najmocniej przegryzione kino drogi jakie istnieje. droga to konieczność, droga to oświecenie.
Fandango, o dojrzewaniu w drodze.
Natural Born Killers, o tym że w drodze możesz być chociaż przez chwilę wolnym człowiekiem - nawet jeśli bardzo z tobą źle.
Proza Faulknera i proza Hemingwaya. Gdzieś tam są korzenie.
Z Faulknerem mam takie skojarzenie:
Pamiętaj, że każda droga prowadzi przez czyjąś wieś. I oczy tych ludzi będą na Ciebie patrzeć i Cię oceniać. Czy tego chcesz czy nie. Czy ci co pochopnie oceniają, są wystarczającą przeszkodą na Twojej drodze aby się zatrzymać?
Z kolei Hemingway uczy że życie to podróż, i że nie trzeba się roztkliwiać. Otwórz oczy i spójrz na horyzont. Spójrz na innych ludzi. Obserwuj ich, co robią. Nie oceniaj pochopnie. Żyj i umrzyj kiedy zechcesz.
Ech. Kończę "blogować" (podobno to teraz "niemodne", ale to temat na inny wpis) i idę oglądać Hitchcocka.
Globalne ocieplenie wg Eskimosów
Angaangaq, szaman Inuków:
Nigdy nie używam określenia zmiana klimatu. Klimat Matki Ziemi zawsze się zmieniał. Dziś jednak stanowczo za szybko topnieje nasz lód. Naukowcy wciąż spierają się, jakie są tego przyczyny. Gdyby zapytano nas, podalibyśmy odpowiedź. Lód nie topnieje z powodu benzyny ani węgla. Topnieje z powodu opon samochodowych, których używają niemal wszyscy. Zawsze kiedy samochód jest w ruchu, zużywają się opony. Wiatr unosi ich malutkie cząsteczki wysoko w powietrze. Krążą wokół całej planety i zimny wiatr Północy spycha je z powrotem na dół. Zamarzają, wiążą się i spadają na ziemię razem ze śniegiem. To właśnie te malutkie czarne drobinki tak mocno się rozgrzewają, gdy tylko wyjdzie słońce, że roztapiają wszystko wokół siebie.
Komu bardziej wierzyć w sprawie topnienia lodu niż Eskimosom? W końcu mają kilkadziesiąt określeń na różne rodzaje śniegu...
W każdym razie, dla mnie to brzmi o wiele bardziej przekonująco niż teoria, jakoby cywilizacyjna emisja CO2 powodowała efekt cieplarniany.
Wyczytane u Geseko von Lüpke, Dawna mądrość na nowe czasy. Rozmowy z uzdrawiaczami i szamanami XXI wieku, ISBN 978-83-7554-129-8
- jest też wywiad z przed-celtyckimi strażnikami drzew z Anglii - MNIAM, dla tych co tak jak ja chodząc po lesie głaszczą drzewa i rozglądają się za entami.