<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="cs">
	<id>http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=Jak_se_st%C3%A1t_hackerem_II</id>
	<title>Jak se stát hackerem II - Historie editací</title>
	<link rel="self" type="application/atom+xml" href="http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=Jak_se_st%C3%A1t_hackerem_II"/>
	<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=Jak_se_st%C3%A1t_hackerem_II&amp;action=history"/>
	<updated>2026-05-13T00:36:37Z</updated>
	<subtitle>Historie editací této stránky</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>http://postgres.cz/index.php?title=Jak_se_st%C3%A1t_hackerem_II&amp;diff=386&amp;oldid=prev</id>
		<title>85.160.73.157 v 24. 2. 2008, 13:12</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=Jak_se_st%C3%A1t_hackerem_II&amp;diff=386&amp;oldid=prev"/>
		<updated>2008-02-24T13:12:36Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nová stránka&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;Implementace pojmenovaných parametrů a variadických funkcí, podpora protokolu JSON&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Tento článek navazuje na článek [[Jak se stát hackerem]].&lt;br /&gt;
&lt;br /&gt;
Autor: [[Pavel Stěhule]] - únor 2008&lt;br /&gt;
&lt;br /&gt;
V Postgresu chybí možnost implementace funkcí s variabilním počtem parametrů - tyto funkce se označují jako variadické. Variadické funkce se sice v pg vyskytují, jedná se ale o implementaci na úrovni parseru, kdy se určité funkce nevolají prostřednictvím executoru funkcí, ale přímo. Tj. nedochází k vyhledávání implementace funkce v tabulce &amp;#039;&amp;#039;pg_proc&amp;#039;&amp;#039;. Tato tabulka obsahuje seznam všech funkcí s fixním počtem parametrů (včetně přetížených funkcí). Vyhledává se na základě shody počtu parametrů, a na základě shody typů případně možnosti přetypování a dosažení shody typů parametrů. Velká většina vestavěných funkcí je nevariadické - pokud mohou mít různé typy parametrů, tak jsou implementovány jako množina přetížených funkcí. Najdou se ale výjimky - např. funkce &amp;#039;&amp;#039;greatest&amp;#039;&amp;#039; nebo &amp;#039;&amp;#039;least&amp;#039;&amp;#039; (případně novější &amp;#039;&amp;#039;xmlforest&amp;#039;&amp;#039;). Při implementaci těchto funkcí bylo nutné modifikovat parser a executor. &lt;br /&gt;
&lt;br /&gt;
Cílem je umožnit implementaci variadických funkcí bez nutnosti modifikace parseru. Plánem je změna procedury, která porovnává shodu parametrů a  to tak, že pokud nedojde ke shodě, tak se vygeneruje dynamicky (bez zápisu do pg_proc) fiktivní funkce, která bude obsahovat nutný počet anyelement parametrů. Aby bylo možné tyto funkce spouštět z jazyka SQL a PL/pgSQL, tak při volání se nevytvoří seznam parametrů, ale pole parametrů - za předpokladu, že skutečné parametry nejsou pole. K tomu je potřeba vytvořit nový fiktivní datovy typ: &amp;#039;&amp;#039;ANYNONARRAYS&amp;#039;&amp;#039;. Funkce může obsahovat pouze jeden parametr tohoto typu a tento parametr musí být uložen jako poslední.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION Least(ANYNONARRAYS)&lt;br /&gt;
RETURNS ANYELEMENT AS $$&lt;br /&gt;
  SELECT MIN($1[i])&lt;br /&gt;
     FROM generate_series(array_lower($1,1),&lt;br /&gt;
                          array_upper($1,1)) g(i)&lt;br /&gt;
$$ LANGUAGE SQL IMMUTABLE;&lt;br /&gt;
&lt;br /&gt;
SELECT Least(10,1,8,8,1,3); --&amp;gt; 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Zavedení nových fiktivních typů==&lt;br /&gt;
Vytvořím nové datové typy ANYPARAMS (variadic k ANY) a ANYNONARRAYS (variadic k ANYNONARRAY). Veškeré vestavěné typy jsou evidovány v souboru (src/include/catalog/pg_type.h). Na základě obsahu tohoto souboru se generují systémové tabulky.&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
DATA(insert OID = 3534 ( anyparams     PGNSP PGUID  4 t p t \054 0 0 0 anyparams_in anyparams_out - - - - - i p f 0 -1 0 _null_ _null_ ));&lt;br /&gt;
#define ANYPARAMSOID          3534&lt;br /&gt;
DATA(insert OID = 3535 ( anynonarrays   PGNSP PGUID  4 t p t \054 0 0 0 anynonarrays_in anynonarrays_out - - - - - i p f 0 -1 0 _null_ _null_ ));&lt;br /&gt;
#define ANYNONARRAYSOID        3535&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Každý datový typ bez výjimky musí mít přiřazeny vstupní a vstupní funkce (/src/include/catalog/pg_proc.h):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 DATA(insert OID = 2964 (  anyparams_in        PGNSP PGUID 12 1 0 f f t f i 1 3534 &amp;quot;2275&amp;quot; _null_ _null_ _null_ anyelement_in - _null_ _null_ ));&lt;br /&gt;
 DESCR(&amp;quot;I/O&amp;quot;);&lt;br /&gt;
 DATA(insert OID = 2967 (  anyparams_out       PGNSP PGUID 12 1 0 f f t f i 1 2275 &amp;quot;3534&amp;quot; _null_ _null_ _null_ anyelement_out - _null_ _null_ ));&lt;br /&gt;
 DESCR(&amp;quot;I/O&amp;quot;);&lt;br /&gt;
 DATA(insert OID = 2965 (  anynonarrays_in      PGNSP PGUID 12 1 0 f f t f i 1 3535 &amp;quot;2275&amp;quot; _null_ _null_ _null_ anyelement_in - _null_ _null_ ));&lt;br /&gt;
 DESCR(&amp;quot;I/O&amp;quot;);&lt;br /&gt;
 DATA(insert OID = 2966 (  anynonarrays_out     PGNSP PGUID 12 1 0 f f t f i 1 2275 &amp;quot;3534&amp;quot; _null_ _null_ _null_ anyelement_out - _null_ _null_ ));&lt;br /&gt;
 DESCR(&amp;quot;I/O&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Reálně nelze do těchto typů uložit žádnou hodnotu. Proto jsou v/v funkce triviální - při volání spustí výjimku (pseudotypes.c):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* &lt;br /&gt;
 * anyparams_in               - input routine for pseudo-type ANYPARAMS. &lt;br /&gt;
 */ &lt;br /&gt;
Datum &lt;br /&gt;
anyparams_in(PG_FUNCTION_ARGS) &lt;br /&gt;
{ &lt;br /&gt;
      ereport(ERROR, &lt;br /&gt;
                      (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), &lt;br /&gt;
                       errmsg(&amp;quot;cannot accept a value of type anyparams&amp;quot;))); &lt;br /&gt;
 &lt;br /&gt;
      PG_RETURN_VOID();                       /* keep compiler quiet */ &lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Po přeložení nesmíme zapomenout inicializovat db cluster příkazem &amp;#039;&amp;#039;initdb&amp;#039;&amp;#039;. Přidáním vestavěných datových typů a funkcí dojde k posunu přiřazených jedinečných identifikátorů, čímž se datové soubory stanou nekompatibilní.&lt;br /&gt;
==Úprava parseru==&lt;br /&gt;
Při parsování dochází k určení Oid funkce na základě shody parametrů volané funkce a záznamu v systémové tabulce pg_proc. Klíčovou roli hraje funkce &amp;#039;&amp;#039;FuncnameGetCandidates&amp;#039;&amp;#039; (/src/backend/catalog/namespace.c). Parametrem této funkce je úplný název funkce (může obsahovat schéma) a počet parametrů. Výstupem je pak seznam potenciálních funkcí, které teoreticky mohou obsloužit požadavek (teoreticky - jinde se kontroluje shoda parametrů). Celý trik je v tom, že pokud zjistíme, že funkce obsahuje parametr ANYPARAMS nebo ANYNONARRAYS, tak nahradíme tento parametr n parametry ANY nebo ANYNONARRAY, tak aby souhlasil seznam parametrů:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Transformace seznamu parametrů na pole parametrů==&lt;br /&gt;
&lt;br /&gt;
Po tomto kroku můžeme psát variadické funkce - zatím pouze v jazyce C.&lt;/div&gt;</summary>
		<author><name>85.160.73.157</name></author>
	</entry>
</feed>