{"id":4138,"date":"2011-11-25T21:39:58","date_gmt":"2011-11-25T19:39:58","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=4138"},"modified":"2011-11-25T21:39:58","modified_gmt":"2011-11-25T19:39:58","slug":"reading-results-of-show-statements-on-server-side","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/reading-results-of-show-statements-on-server-side","title":{"rendered":"Reading results of SHOW statements, on server side"},"content":{"rendered":"<p><strong>SHOW<\/strong> statements are show stoppers on server side. While clients can get a <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/show.html\">SHOW statement<\/a> as a result set just as any normal <strong>SELECT<\/strong>, things are not as such on server side.<\/p>\n<p>On server side, that is, from within MySQL itself, one <em>cannot<\/em>:<\/p>\n<blockquote>\n<pre>SELECT `Database` FROM (SHOW DATABASES);<\/pre>\n<\/blockquote>\n<p>One <em>cannot<\/em>:<\/p>\n<blockquote>\n<pre>DECLARE show_cursor CURSOR FOR SHOW TABLES;<\/pre>\n<\/blockquote>\n<p>One <em>cannot<\/em>:<\/p>\n<blockquote>\n<pre>SHOW TABLES INTO OUTFILE '\/tmp\/my_file.txt';<\/pre>\n<\/blockquote>\n<p>So it is impossible to get the results with a query; impossible to get the results from a stored routine; impossible to get the results by file reading&#8230;<\/p>\n<h4>Bwahaha! A hack!<\/h4>\n<p>For some <strong>SHOW<\/strong> statements, there is a way around this. I&#8217;ve been banging my head against the wall for weeks now on this. Now I have a partial solution: I&#8217;m able to read <strong>SHOW<\/strong> output for several <strong>SHOW<\/strong> statements. Namely, those <strong>SHOW<\/strong> statements <a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/extended-show.html\">which allow a LIKE or a WHERE<\/a> clause.<\/p>\n<p>For example, most are familiar with the following syntax:<\/p>\n<blockquote>\n<pre>USE mysql;\r\nSHOW TABLE STATUS LIKE 'user';<\/pre>\n<\/blockquote>\n<p>However not so many know that any <strong>SHOW<\/strong> statement which accepts <strong>LIKE<\/strong>, can also accept <strong>WHERE<\/strong>:<!--more--><\/p>\n<blockquote>\n<pre>SHOW TABLE STATUS WHERE Name='user'\\G\r\n*************************** 1. row ***************************\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Name: user\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Engine: MyISAM\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Version: 10\r\n\u00a0\u00a0\u00a0\u00a0 Row_format: Dynamic\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Rows: 17\r\n\u00a0Avg_row_length: 69\r\n\u00a0\u00a0\u00a0 Data_length: 1184\r\nMax_data_length: 281474976710655\r\n\u00a0\u00a0 Index_length: 2048\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 Data_free: 0\r\n\u00a0Auto_increment: NULL\r\n\u00a0\u00a0\u00a0 Create_time: 2010-10-03 08:23:48\r\n\u00a0\u00a0\u00a0 Update_time: 2011-07-30 19:31:00\r\n\u00a0\u00a0\u00a0\u00a0 Check_time: NULL\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 Collation: utf8_bin\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Checksum: NULL\r\n\u00a0Create_options:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Comment: Users and global privileges<\/pre>\n<\/blockquote>\n<p>It&#8217;s not just about &#8220;<strong>Name<\/strong>&#8220;. I can filter using any column I like:<\/p>\n<blockquote>\n<pre>SHOW TABLE STATUS WHERE Rows &gt; 1000;\r\nSHOW TABLE STATUS WHERE Rows &gt; 1000 AND Index_length &gt; 65536;<\/pre>\n<\/blockquote>\n<p>etc.<\/p>\n<p>If you&#8217;ve been to my talk on <a href=\"http:\/\/www.percona.com\/live\/london-2011\/session\/programmatic-queries-things-you-can-code-with-sql\/\">Programmatic Queries: things you can code with SQL<\/a>, you have a good guess as for where I&#8217;m taking this.<\/p>\n<h4>Where there&#8217;s WHERE, there&#8217;s code<\/h4>\n<p>I can write code within the <strong>WHERE<\/strong> clause. Specifically, I can work with user defined variables. Shall we cut to the point and provide with an example?<\/p>\n<blockquote>\n<pre>mysql&gt; SET @databases := '';\r\n\r\nmysql&gt; SHOW DATABASES WHERE (@databases := CONCAT(@databases, `Database`, ',')) IS NULL;\r\n\r\nmysql&gt; SELECT @databases;\r\n+-------------------------------------------------------------------+\r\n| @databases\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n+-------------------------------------------------------------------+\r\n| information_schema,common_schema,mycheckpoint,mysql,sakila,world, |\r\n+-------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<p>Let&#8217;s discuss the above. We:<\/p>\n<ul>\n<li>Set a user variables called <strong>@databases<\/strong> to an empty text<\/li>\n<li>Iterate through the <strong>SHOW DATABASES<\/strong> rowset. The <strong>WHERE<\/strong> clause is always <em>false<\/em> (the expression is in fact <strong>NOT NULL<\/strong> for all rows), so rows are not printed out, and we get an empty result set (we&#8217;re not really interested in a result set here, since there&#8217;s no way to read it anyhow).<\/li>\n<li>However we do take care to &#8220;remember&#8221; the value we visit, by concatenating the <strong>`Database`<\/strong> column value.<\/li>\n<li>We end up with a delimited string of database names. You&#8217;ll forgive the ending <strong>&#8216;,&#8217;<\/strong>. This is just a simple example, it is of no importance.<\/li>\n<\/ul>\n<h4>Further notes<\/h4>\n<p>What can we do with the concatenated list of database names? Whatever we want to. We can parse it again, <strong>INSERT<\/strong> it <strong>INTO<\/strong> some table, save to file, iterate, what have you!<\/p>\n<p>We can wrap the above in a stored routine. Alas, not with a stored function, since the <strong>SHOW<\/strong> command, although returns with an empty result set, does return with a result set, not allowed withing functions.<strong><\/strong><\/p>\n<h4>Limitations<\/h4>\n<ul>\n<li>Sadly, <strong>SHOW SLAVE STATUS<\/strong>, <strong>SHOW MASTER LOGS<\/strong> etc., do not support <strong>LIKE<\/strong> or <strong>WHERE<\/strong> syntax. Bummer.<\/li>\n<li>Stored functions, as just mentioned, cannot utilize this hack. Hey, I&#8217;m still working on this!<\/li>\n<\/ul>\n<h4>To what use?<\/h4>\n<p>Originally I wanted to avoid the time &amp; locking it takes for <strong>INFORMATION_SCHEMA<\/strong> queries, such as on <strong>TABLES<\/strong>, <strong>COLUMNS<\/strong>, etc. Ironically, in a few days apart I&#8217;ve found <em>another<\/em> interesting solution (well, two, actually) to manage reads from <strong>INFORMATION_SCHEMA<\/strong> with less overhead than in normal use. I&#8217;ll talk about that another time; am about to use this in <a href=\"http:\/\/code.google.com\/p\/common-schema\/\" rel=\"nofollow\">common_schema<\/a>.<\/p>\n<h4>Further notes<\/h4>\n<p>I met <a href=\"http:\/\/rpbouman.blogspot.com\/\">Roland<\/a> in <a href=\"http:\/\/www.percona.com\/live\/london-2011\/\">London<\/a>, and he liked the solution. As <a href=\"http:\/\/www.mysqlperformanceblog.com\/author\/baron\/\">Baron<\/a> joined, Roland said: &#8220;Baron, do you know Shlomi devised a method to read the output of <strong>SHOW<\/strong> commands?&#8221;<\/p>\n<p>And Baron said: &#8220;Without using files? Then a <strong>SHOW<\/strong> statement can have a <strong>WHERE<\/strong> clause, in which case you can use a variable&#8221;, and went on looking for his wife.<\/p>\n<p>And we remained speechless.<\/p>\n<p>[UPDATE: I&#8217;ve manually changed timestamp of this post due to failure in its aggregation in planet.mysql, being a major source of incoming traffic to this site]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>SHOW statements are show stoppers on server side. While clients can get a SHOW statement as a result set just as any normal SELECT, things are not as such on server side. On server side, that is, from within MySQL itself, one cannot: SELECT `Database` FROM (SHOW DATABASES); One cannot: DECLARE show_cursor CURSOR FOR SHOW [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[67,71,24,21],"class_list":["post-4138","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-common_schema","tag-hacks","tag-information_schema","tag-sql"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-14K","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4138","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=4138"}],"version-history":[{"count":50,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4138\/revisions"}],"predecessor-version":[{"id":4424,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/4138\/revisions\/4424"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=4138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=4138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=4138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}