<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tamkovich.com: Телеком/VoIP блог &#187; MySQL</title>
	<atom:link href="http://tamkovich.com/tag/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://tamkovich.com</link>
	<description>Современные технологии: Asterisk, SIP, Kamailio, Linux, Cisco, Linksys</description>
	<lastBuildDate>Mon, 30 Jan 2012 11:42:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>MySQL: о пользе вложенных запросов</title>
		<link>http://tamkovich.com/2010/11/mysql-nested-queries/</link>
		<comments>http://tamkovich.com/2010/11/mysql-nested-queries/#comments</comments>
		<pubDate>Sun, 28 Nov 2010 09:38:08 +0000</pubDate>
		<dc:creator>Сергей Тамкович</dc:creator>
				<category><![CDATA[Разное]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://tamkovich.com/?p=1624</guid>
		<description><![CDATA[Не так давно, начиная с версии MySQL 4.1 &#8211; СУБД MySQL получила поддержку так называемых вложенных запросов. Большинство вложенных запросов могут быть переписаны с помощью стандартного join. Например вот такой вложенный запрос: SELECT a, b FROM t1 WHERE c IN &#40;SELECT d FROM t2&#41;; Можно безболезненно заменить эквивалентом без вложенного запроса: SELECT t1.a, t1.b FROM [...]]]></description>
			<content:encoded><![CDATA[<p align=justify>
Не так давно, начиная с версии MySQL 4.1 &#8211; СУБД MySQL получила поддержку так называемых вложенных запросов. Большинство вложенных запросов могут быть переписаны с помощью стандартного join. Например вот такой вложенный запрос:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">,</span> b <span style="color: #993333; font-weight: bold;">FROM</span> t1 <span style="color: #993333; font-weight: bold;">WHERE</span> c <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> d <span style="color: #993333; font-weight: bold;">FROM</span> t2<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>Можно безболезненно заменить эквивалентом без вложенного запроса:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> t1<span style="color: #66cc66;">.</span>a<span style="color: #66cc66;">,</span> t1<span style="color: #66cc66;">.</span>b <span style="color: #993333; font-weight: bold;">FROM</span> t1<span style="color: #66cc66;">,</span> t2 <span style="color: #993333; font-weight: bold;">WHERE</span> t1<span style="color: #66cc66;">.</span>c<span style="color: #66cc66;">=</span>t2<span style="color: #66cc66;">.</span>d;</pre></div></div>

<p>Однако, существует масса задач, решение которых без использования вложенных запросов &#8211; крайне уродливо или же его нет вообще. Приведу пример, близкий любителям <a href=http://tamkovich.com/asterisk/ >Asterisk</a>.
</p>
<p><span id="more-1624"></span></p>
<p align=justify>
Задача не особо экзотическая &#8211; имея таблицу <a href=http://www.voip-info.org/wiki/view/Asterisk+cdr+mysql >CDR</a> с записями о состоявшихся звонках оценить загрузку сотрудников отвечающих на телефон, по дням недели. Сотрудники, чью загрузку будем оценивать, имеют внутренние номера 102 и 117. По этому, критерием отбора CDR записей будет поле dstchannel начинающиеся с &#8216;<a href=http://tamkovich.com/tag/sip/ >SIP</a>/102&#8242; или с &#8216;<a href=http://tamkovich.com/tag/sip/ >SIP</a>/117&#8242;. В первую очередь, нам необходимо просуммировать звонки по дням что бы получить суточные данные о количестве и длительность звонков, делается это тривиальным запросом
</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span>calldate<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dt<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">SUM</span><span style="color: #66cc66;">&#40;</span>billsec<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">/</span><span style="color: #cc66cc;">3600</span> <span style="color: #993333; font-weight: bold;">AS</span> hours<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span>billsec<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> calls
<span style="color: #993333; font-weight: bold;">FROM</span> cdr 
<span style="color: #993333; font-weight: bold;">WHERE</span> calldate<span style="color: #66cc66;">&gt;</span><span style="color: #ff0000;">'2010-10-01 00:00:00'</span> <span style="color: #993333; font-weight: bold;">AND</span> calldate<span style="color: #66cc66;">&lt;</span><span style="color: #ff0000;">'2010-11-01 00:00:00'</span> 
<span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span>dstchannel <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'SIP/102%'</span> <span style="color: #993333; font-weight: bold;">OR</span> dstchannel <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'SIP/117%'</span><span style="color: #66cc66;">&#41;</span> 
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span>calldate<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p align=justify>
В этом запросе будут выбраны: дата, длительность звонков преведенная к часам и количество звонков за указазнную дату. Суть вложенных SQL запросов, заключается в том, что результаты одного запроса можно использовать как таблицу для другого. Имея распределение звонков и их длительности по датам мы можем посчитать загрузку сотрудников по дням недели. Для этого нам понадобится функция DAYNAME() которая вычесляет название дня недели по дате. В результате мы имеем SQL запрос который с помощью функции AVG() считает среднее количество и среднюю длительность звонков за сутки, группируя данные по дням недели:
</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> DAYNAME<span style="color: #66cc66;">&#40;</span>dt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> AVG<span style="color: #66cc66;">&#40;</span>hours<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> AVG<span style="color: #66cc66;">&#40;</span>calls<span style="color: #66cc66;">&#41;</span> 
<span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#40;</span>
    <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span>calldate<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> dt<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">SUM</span><span style="color: #66cc66;">&#40;</span>billsec<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">/</span><span style="color: #cc66cc;">3600</span> <span style="color: #993333; font-weight: bold;">AS</span> hours<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span>billsec<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> calls 
    <span style="color: #993333; font-weight: bold;">FROM</span> cdr
    <span style="color: #993333; font-weight: bold;">WHERE</span> calldate<span style="color: #66cc66;">&gt;</span><span style="color: #ff0000;">'2010-10-01 00:00:00'</span> <span style="color: #993333; font-weight: bold;">AND</span> calldate<span style="color: #66cc66;">&lt;</span><span style="color: #ff0000;">'2010-11-01 00:00:00'</span> 
    <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span>dstchannel <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'SIP/102%'</span> <span style="color: #993333; font-weight: bold;">OR</span> dstchannel <span style="color: #993333; font-weight: bold;">LIKE</span> <span style="color: #ff0000;">'SIP/117%'</span><span style="color: #66cc66;">&#41;</span> 
    <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #993333; font-weight: bold;">DATE</span><span style="color: #66cc66;">&#40;</span>calldate<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> t1 
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> DAYNAME<span style="color: #66cc66;">&#40;</span>dt<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p align=justify>
На выходе получаем интересующий нас результат:
</p>
<pre>
+-------------+------------+------------+
| DAYNAME(dt) | AVG(hours) | AVG(calls) |
+-------------+------------+------------+
| Friday      | 2.89125000 |    96.0000 |
| Monday      | 4.06492500 |   139.0000 |
| Saturday    | 4.36542500 |   170.5000 |
| Sunday      | 2.72717500 |    98.0000 |
| Thursday    | 2.80562500 |    90.5000 |
| Tuesday     | 3.93172500 |   118.2500 |
| Wednesday   | 3.01332500 |    99.7500 |
+-------------+------------+------------+
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tamkovich.com/2010/11/mysql-nested-queries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kamailio: загружаем много данных с помощью db_mysql</title>
		<link>http://tamkovich.com/2010/10/kamailio-how-to-load-big-table-with-db_mysql/</link>
		<comments>http://tamkovich.com/2010/10/kamailio-how-to-load-big-table-with-db_mysql/#comments</comments>
		<pubDate>Wed, 20 Oct 2010 09:42:38 +0000</pubDate>
		<dc:creator>Сергей Тамкович</dc:creator>
				<category><![CDATA[ITSP]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[Сделай сам]]></category>
		<category><![CDATA[Kamailio]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://tamkovich.com/?p=1572</guid>
		<description><![CDATA[В Kamailio/OpenSIPS, как в любом взрослом проекте, имеется некоторое количество &#171;прокладочных&#187; интерфейсов. Задача этих интерфейсов &#8211; унификация. Например, с помощью mem/mem.h унифицирована работа с памятью. Интерфейс предоставляет набор вызовов pkg_malloc/pkg_free для работы с обычной памятью и shm_malloc/shm_free для работы с разделяемой памятью. Благодаря унификации работы с памятью &#8211; Kamailio портирован на множество различных платформ. Другим [...]]]></description>
			<content:encoded><![CDATA[<p align=justify>
В Kamailio/OpenSIPS, как в любом взрослом проекте, имеется некоторое количество &laquo;прокладочных&raquo; интерфейсов. Задача этих интерфейсов &#8211; унификация. Например, с помощью mem/mem.h унифицирована работа с памятью. Интерфейс предоставляет набор вызовов pkg_malloc/pkg_free для работы с обычной памятью и shm_malloc/shm_free для работы с разделяемой памятью. Благодаря унификации работы с памятью &#8211; Kamailio портирован на множество различных платформ. Другим интерфейсом-прокладкой является интерфейс работы с базами данных <a href=http://www.asipto.com/pub/kamailio-devel-guide/#c09database>DB API</a>. Базовая работа с этим интерфейсом хорошо описана в <a href=http://www.asipto.com/pub/kamailio-devel-guide/>KAMAILIO (OPENSER) Devel Guide</a>.
</p>
<p><span id="more-1572"></span></p>
<p align=justify>
Классическая операция получения данных из MySQL выглядит следующим образом:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">snprintf<span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        <span style="color: #ff0000;">&quot;select n.id,n.name,n.ip,n.port,n.capacity,COUNT(c.node) 
         from cluster_nodes n left join active_calls c on (n.name=c.node) 
         where online=1 group by n.name&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
sql_cmd.<span style="color: #202020;">s</span> <span style="color: #339933;">=</span> sqlcmd<span style="color: #339933;">;</span>
sql_cmd.<span style="color: #202020;">len</span> <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
LOG<span style="color: #009900;">&#40;</span>L_DBG<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Trying to execute SQL: '%s'<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> sqlcmd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fres <span style="color: #339933;">=</span> dbf.<span style="color: #202020;">raw_query</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>sql_cmd<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fres <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        total <span style="color: #339933;">=</span> RES_ROW_N<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>total <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> total<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        node <span style="color: #339933;">=</span> shm_malloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> ci_li_node<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>node <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                LM_ERR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Could not allocate shared memory<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
                        <span style="color: #009900;">&#125;</span>
                        node<span style="color: #339933;">-&gt;</span>id <span style="color: #339933;">=</span> RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">int_val</span><span style="color: #339933;">;</span>
                        node<span style="color: #339933;">-&gt;</span>calls_init <span style="color: #339933;">=</span> RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">int_val</span><span style="color: #339933;">;</span>
                        node<span style="color: #339933;">-&gt;</span>calls_current <span style="color: #339933;">=</span> node<span style="color: #339933;">-&gt;</span>calls_init<span style="color: #339933;">;</span>
                        node<span style="color: #339933;">-&gt;</span>calls_max <span style="color: #339933;">=</span> RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">int_val</span><span style="color: #339933;">;</span>
                        node<span style="color: #339933;">-&gt;</span>port <span style="color: #339933;">=</span> RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">int_val</span><span style="color: #339933;">;</span>
                        snprintf<span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>name<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> 
                                <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">str_val</span>.<span style="color: #202020;">s</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        snprintf<span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>ip<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">-&gt;</span>ip<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> 
                                <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">values</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">val</span>.<span style="color: #202020;">str_val</span>.<span style="color: #202020;">s</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        node<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
&nbsp;
                        total_max <span style="color: #339933;">+=</span> node<span style="color: #339933;">-&gt;</span>calls_max<span style="color: #339933;">;</span>
                        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">=</span> node<span style="color: #339933;">;</span>
                                mylist<span style="color: #339933;">-&gt;</span>first <span style="color: #339933;">=</span> node<span style="color: #339933;">;</span>
                        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                                mylist<span style="color: #339933;">-&gt;</span>last<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">=</span> node<span style="color: #339933;">;</span>
                                mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">=</span> node<span style="color: #339933;">;</span>
                        <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#125;</span>
                LOG<span style="color: #009900;">&#40;</span>L_DBG<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;PRELOAD TOTAL: [servers] %d items = %lu bytes.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> 
                        i<span style="color: #339933;">,</span> i <span style="color: #339933;">*</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> ci_li_node<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                mylist<span style="color: #339933;">-&gt;</span>dt <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>       
        dbf.<span style="color: #202020;">free_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Как видим из простого примера, получение данных из MySQL сводится к трём действиям:
<ol>
<li>Отправляем SQL запрос с помощью команды raw_query.
<li>Читаем результаты с помощью макросов RES_ROW_N и RES_ROWS
<li>Подчищаем за собой память с помощью free_result</ol>
<p>Пока мы действуем по шаблону &#8211; всё отлично работает.
</p>
<p align=justify >
Но стоит нам захотеть чего то большего &#8211; и подход придётся менять. Например приведенным выше кодом нельзя загрузить за раз большую таблицу (тысячи записей). Прокладочные интерфейсы БД и памяти &#8211; накладываются друг на друга и возникают интересные эффекты. Дело в том, что при попытке загрузить большую таблицу целиком &#8211; db_mysql выделяет память под неё &#8211; одним куском. С другой стороны, pkg_free не освобождает память моментально, а лишь помечает её как готовую к очистке. Всё это приводит к тому, что загрузка большой таблицы срабатывает 2 раза подряд, а на третий возникает ошибка &#8211; недостаточно памяти.
</p>
<p align=justify >
Зачем загружать всю таблицу целиком &#8211; спросите вы? Вариантов может быть очень много &#8211; самый распространённый, пожалуй, &#8211; для того, что бы закешировать данные из БД. На одной СУБД далеко не уедешь, даже на такой быстрой как MySQL. Итак, что же нужно сделать для того, что бы обойти проблемы с памятью? Ответ очень простой: нужно воспользоваться вызовом fetch_result. К сожалению, применение этого вызова не расписано в <a href=http://www.asipto.com/pub/kamailio-devel-guide/>KAMAILIO (OPENSER) Devel Guide</a>, но, как известно, лучшая документация это исходный код. С практикой применения этого вызова можно ознакомиться в модулях Kamailio:</p>
<pre>
[root@sipproxy kamailio-3.0.3]# grep -l fetch_result */*/*.c
...
modules_k/dialog/dlg_db_handler.c
modules_k/drouting/dr_load.c
modules_k/htable/ht_db.c
modules_k/pdt/pdt.c
...
</pre>
<p>Вызов fetch_result позволяет указать сколько строк мы хотим поместить в память. Таким образом, вызывая fetch_result в цикле &#8211; мы обработаем все строки возвращённые базой данных по порциям. Если вы планируете использовать fetch_result самостоятельно, необходимо передать NULL в качестве указателя db_res_t** _r у функций raw_query(&#8230;) и query(&#8230;). Для наглядности, рассмотрим похожий кусок кода, написанный с использованием вызова fetch_result. Параметр ci_preload_chunk задаёт количество строк загружаемых в память за 1 вызов:
</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">snprintf<span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        <span style="color: #ff0000;">&quot;select name,owner from sip where host='dynamic' and owner&gt;0&quot;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
sql_cmd.<span style="color: #202020;">s</span> <span style="color: #339933;">=</span> sqlcmd<span style="color: #339933;">;</span>
sql_cmd.<span style="color: #202020;">len</span> <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>sqlcmd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
LOG<span style="color: #009900;">&#40;</span>L_DBG<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Trying to execute SQL: '%s'<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> sqlcmd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fres <span style="color: #339933;">=</span> dbf.<span style="color: #202020;">raw_query</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>sql_cmd<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fres <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        LOG<span style="color: #009900;">&#40;</span>L_DBG<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Trying to fetch first %d items.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> ci_preload_chunk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>dbf.<span style="color: #202020;">fetch_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>res<span style="color: #339933;">,</span> ci_preload_chunk<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                LM_ERR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Error while fetching result<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        dbf.<span style="color: #202020;">free_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>       
        total <span style="color: #339933;">=</span> RES_ROW_N<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        LOG<span style="color: #009900;">&#40;</span>L_DBG<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%d first items fetched.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> total<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>total <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> total<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                row <span style="color: #339933;">=</span> RES_ROWS<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> i<span style="color: #339933;">;</span>
                                u <span style="color: #339933;">=</span> shm_malloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> ci_li_sipuser<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>u <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                        LM_ERR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Could not allocate shared memory<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
                                <span style="color: #009900;">&#125;</span>       
                                u<span style="color: #339933;">-&gt;</span>sipaccount <span style="color: #339933;">=</span> atoi<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>VAL_STRING<span style="color: #009900;">&#40;</span>ROW_VALUES<span style="color: #009900;">&#40;</span>row<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                u<span style="color: #339933;">-&gt;</span>customer <span style="color: #339933;">=</span> VAL_INT<span style="color: #009900;">&#40;</span>ROW_VALUES<span style="color: #009900;">&#40;</span>row<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                u<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
                                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                        mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">=</span> u<span style="color: #339933;">;</span>
                                        mylist<span style="color: #339933;">-&gt;</span>first <span style="color: #339933;">=</span> u<span style="color: #339933;">;</span>
                                <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                                        mylist<span style="color: #339933;">-&gt;</span>last<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">=</span> u<span style="color: #339933;">;</span>
                                        mylist<span style="color: #339933;">-&gt;</span>last <span style="color: #339933;">=</span> u<span style="color: #339933;">;</span>
                                <span style="color: #009900;">&#125;</span>
                                mylist<span style="color: #339933;">-&gt;</span>elements<span style="color: #339933;">++;</span>
                                cnt<span style="color: #339933;">++;</span>
                        <span style="color: #009900;">&#125;</span>
                        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>dbf.<span style="color: #202020;">fetch_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>res<span style="color: #339933;">,</span> ci_preload_chunk<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                LM_ERR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Error while fetching result<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                                        dbf.<span style="color: #202020;">free_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                                <span style="color: #009900;">&#125;</span>
                                <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
                        <span style="color: #009900;">&#125;</span>
                        total <span style="color: #339933;">=</span> RES_ROW_N<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>total <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                dbf.<span style="color: #202020;">free_result</span><span style="color: #009900;">&#40;</span>db_handle<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://tamkovich.com/2010/10/kamailio-how-to-load-big-table-with-db_mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asterisk realtime теперь различает NULL и пустые строки</title>
		<link>http://tamkovich.com/2010/01/asterisk-realtime-mysql-null/</link>
		<comments>http://tamkovich.com/2010/01/asterisk-realtime-mysql-null/#comments</comments>
		<pubDate>Sat, 02 Jan 2010 12:16:37 +0000</pubDate>
		<dc:creator>Сергей Тамкович</dc:creator>
				<category><![CDATA[Asterisk]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://tamkovich.com/?p=849</guid>
		<description><![CDATA[Новогодние каникулы &#8211; отличное время для обновления вашей системы. Есть время подумать, взвесить все &#171;за&#187; и &#171;против&#187; и внимательно накатить необходимые обновления. Не стали исключением и эти праздники. Неприятный сюрприз ждал меня в модуле res_config_mysql из Asterisk-addons. 4 декабря, в него был добавлен сомнительный патч: /* Encode NULL values separately from blank values, for the [...]]]></description>
			<content:encoded><![CDATA[<p align=justify>
Новогодние каникулы &#8211; отличное время для обновления вашей системы. Есть время подумать, взвесить все &laquo;за&raquo; и &laquo;против&raquo; и внимательно накатить необходимые обновления. Не стали исключением и эти праздники.
</p>
<p align=justify>
Неприятный сюрприз ждал меня в модуле res_config_mysql из <a href=http://tamkovich.com/asterisk/ >Asterisk</a>-addons. 4 декабря, в него был добавлен сомнительный патч:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* Encode NULL values separately from blank values, for the Realtime API */</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>row<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    row<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ast_strlen_zero<span style="color: #009900;">&#40;</span>row<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    row<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot; &quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Этот гениальный код, означает, что теперь поле, имеющее значение NULL в MySQL, видно в <a href=http://tamkovich.com/asterisk/ >Asterisk</a>, как пустая строка. А пустая строка в MySQL, в <a href=http://tamkovich.com/asterisk/ >Asterisk</a>, волшебным образом превращается в строку с одним пробелом. Представьте, что все ваши пустые строки, превратились в строку с одним пробелом! Т.е. если вы, использовали пустые строки и не использовали NULL &#8211; ваши настройки больше невалидны! Проблемы вылезут на каждом углу, например вот такие ошибки, при звонке на <a href=http://tamkovich.com/cisco/ >Cisco</a> AS5350: <a href=http://tamkovich.com/tag/sip/ >SIP</a>/2.0 400 Bad Request &#8211; &#8216;Malformed/Missing FROM: field&#8217;. Эта ошибка вызвана тем, что пустые строки в полях fromuser и fromdomain превратились в непустые. В результате заголовок From выглядит вот так:</p>
<pre>
From: "1000" &lt;<a href=http://tamkovich.com/tag/sip/ >SIP</a>: @ &gt;;tag=as3e28b5d2
</pre>
</p>
<p align=justify>
Остаётся только гадать, как подобный патч мог быть включен в стабильную ветку <a href=http://tamkovich.com/asterisk/ >Asterisk</a>.
</p>
<ul>
<li> <a href=https://issues.asterisk.org/view.php?id=16138 >0016138: [patch] realtime function does not return pair when database value is null</a>
<li> <a href=http://svnview.digium.com/svn/asterisk-addons/branches/1.6.0/res/res_config_mysql.c?r1=983&#038;r2=1070 >Diff of /branches/1.6.0/res/res_config_mysql.c</a>
<li> <a href=https://issues.asterisk.org/view.php?id=16533 >Мой багрепорт на issues.asterisk.org</a>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tamkovich.com/2010/01/asterisk-realtime-mysql-null/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

