[Pdns-dev] [PATCH] Allow gmysql backend to call stored procedures
Jonathan Oddy
jonathan.oddy at hostway.co.uk
Wed Nov 5 17:46:01 CET 2008
Calling stored procedures using the mysql client library requires that
the connection is opened with the CLIENT_MULTI_RESULTS flag, and that
the client is capable of dealing with multiple result sets. The attached
patch sets that flag and copes with multiple result sets by ignoring
(and freeing) all but the first one returned.
Why this crazy requirement? I've got a database based on the myDNS
schema and can't easily change our management tools to migrate away from
said schema. Unfortunately the performance of a VIEW that presents the
data in a format suitable for pDNS is dreadful, as there are significant
differences between myDNS and pDNS behaviour. I've also considered
triggers on the myDNS tables that update pDNS friendly tables, however
that came with a different set of problems.
So, thus came about the attached patch and set of stored procedures. The
former might be useful for other people, the latter I've attached to
satisfy the readers' morbid curiosity. I'm well aware that performance
will not be ideal, however it seems to work and it's faster than the
alternatives.
Any feedback would be appreciated.
--
Jonathan Oddy
Senior Linux Systems Engineer
Hostway UK
-------------- next part --------------
delimiter //
DROP PROCEDURE pdns_find_zone//
CREATE PROCEDURE pdns_find_zone(IN fqdn VARCHAR(255), OUT zoneid INT, OUT host VARCHAR(255), OUT domain VARCHAR(255))
BEGIN
DECLARE npos INT;
SET npos = 1;
SET zoneid = NULL;
SET host = '';
SET domain = fqdn;
SELECT id INTO zoneid FROM Zone WHERE origin = CONCAT(domain, '.');
SET npos = LOCATE('.', domain);
WHILE npos != 0 AND zoneid IS NULL
DO
SET host = CONCAT(host, IF(host != '','.',''), LEFT(domain, npos-1));
SET domain = RIGHT(domain, LENGTH(domain)-npos);
SELECT id INTO zoneid FROM Zone WHERE origin = CONCAT(domain, '.');
SET npos = LOCATE('.', domain);
END WHILE;
IF zoneid IS NULL
THEN
SET host = NULL;
SET domain = NULL;
END IF;
END;//
DROP PROCEDURE pdns_build_soa//
CREATE PROCEDURE pdns_build_soa(IN zoneid INT, OUT soa VARCHAR(255))
BEGIN
SELECT CONCAT(z.ns, ' ', z.mbox, ' ', z.serial, ' ', z.refresh, ' ', z.retry, ' ', z.expire, ' ', z.ttl) INTO soa FROM Zone AS z WHERE z.id = zoneid;
END;//
DROP PROCEDURE pdns_basic_query//
CREATE PROCEDURE pdns_basic_query (type VARCHAR(6), name VARCHAR(255))
BEGIN
DECLARE zoneid INT;
DECLARE hname VARCHAR(255);
DECLARE dname VARCHAR(255);
DECLARE soar VARCHAR(255);
CALL pdns_find_zone(name, zoneid, hname, dname);
IF zoneid IS NOT NULL
THEN
IF type = 'SOA'
THEN
IF name = dname
THEN
CALL pdns_build_soa(zoneid, soar);
SELECT soar AS content, 10800 AS ttl, 0 AS prio, 'SOA' AS type, zoneid AS domain_id, dname AS name;
ELSE
SELECT 1 LIMIT 0;
END IF;
ELSE
SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1 AND zr.type = type;
END IF;
ELSE
SELECT 1 LIMIT 0;
END IF;
END;//
DROP PROCEDURE pdns_id_query//
CREATE PROCEDURE pdns_id_query (type VARCHAR(6), name VARCHAR(255), domainid INT)
BEGIN
DECLARE zoneid INT;
DECLARE hname VARCHAR(255);
DECLARE dname VARCHAR(255);
DECLARE soar VARCHAR(255);
CALL pdns_find_zone(name, zoneid, hname, dname);
IF zoneid IS NOT NULL AND domainid = zoneid
THEN
IF type = 'SOA'
THEN
IF name = dname
THEN
CALL pdns_build_soa(zoneid, soar);
SELECT soar AS content, 10800 AS ttl, 0 AS prio, 'SOA' AS type, zoneid AS domain_id, dname AS name;
ELSE
SELECT 1 LIMIT 0;
END IF;
ELSE
SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1 AND zr.type = type;
END IF;
ELSE
SELECT 1 LIMIT 0;
END IF;
END;//
DROP PROCEDURE pdns_any_query//
CREATE PROCEDURE pdns_any_query (name VARCHAR(255))
BEGIN
DECLARE zoneid INT;
DECLARE hname VARCHAR(255);
DECLARE dname VARCHAR(255);
DECLARE soar VARCHAR(255);
CALL pdns_find_zone(name, zoneid, hname, dname);
IF zoneid IS NOT NULL
THEN
IF name = dname
THEN
CALL pdns_build_soa(zoneid, soar);
SELECT soar AS content, 10800 AS ttl, 0 AS prio, 'SOA' AS type, zoneid AS domain_id, dname AS name UNION SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1;
ELSE
SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1;
END IF;
ELSE
SELECT 1 LIMIT 0;
END IF;
END;//
DROP PROCEDURE pdns_any_id_query//
CREATE PROCEDURE pdns_any_id_query (name VARCHAR(255), domainid INT)
BEGIN
DECLARE zoneid INT;
DECLARE hname VARCHAR(255);
DECLARE dname VARCHAR(255);
DECLARE soar VARCHAR(255);
CALL pdns_find_zone(name, zoneid, hname, dname);
IF zoneid IS NOT NULL AND domainid = zoneid
THEN
IF name = dname
THEN
CALL pdns_build_soa(zoneid, soar);
SELECT soar AS content, 10800 AS ttl, 0 AS prio, 'SOA' AS type, zoneid AS domain_id, dname AS name UNION SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1;
ELSE
SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',dname))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, name AS name FROM ZoneRecord as zr WHERE zr.zone = zoneid AND (zr.name = hname OR zr.name = CONCAT(name, '.')) AND zr.active = 1;
END IF;
ELSE
SELECT 1 LIMIT 0;
END IF;
END;//
DROP PROCEDURE pdns_list_query//
CREATE PROCEDURE pdns_list_query (domainid INT)
BEGIN
DECLARE domain VARCHAR(255);
DECLARE soar VARCHAR(255);
SELECT origin INTO domain FROM Zone WHERE id = domainid;
IF domain IS NOT NULL
THEN
CALL pdns_build_soa(domainid, soar);
SELECT TRIM(TRAILING '.' FROM IF(zr.type NOT IN ('NS', 'MX', 'CNAME', 'PTR') OR RIGHT(zr.data, 1) = '.',zr.data,CONCAT(zr.data,'.',domain))) AS content, zr.ttl AS ttl, zr.aux AS prio, zr.type AS type, zr.zone AS domain_id, TRIM(TRAILING '.' FROM IF(zr.name IS NULL OR zr.name = '',domain,IF(RIGHT(zr.name, 1) = '.',zr.name,CONCAT(zr.name, '.', domain)))) AS name FROM ZoneRecord as zr WHERE zr.zone = domainid AND zr.active = 1 AND (RIGHT(zr.name, 1) != '.' OR (LENGTH(TRIM(TRAILING '.' FROM domain)) <= LENGTH(TRIM(TRAILING '.' FROM zr.name)) AND (RIGHT(TRIM(TRAILING '.' FROM (zr.name)), LENGTH(TRIM(TRAILING '.' FROM (domain)))) = TRIM(TRAILING '.' FROM (domain))))) UNION SELECT soar AS content, 10800 AS ttl, 0 AS prio, 'SOA' AS type, domainid AS domain_id, domain AS name;
ELSE
SELECT 1 LIMIT 0;
END IF;
END;//
delimiter ;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pdns_multi_results_support.diff
Type: text/x-diff
Size: 722 bytes
Desc: not available
Url : http://mailman.powerdns.com/pipermail/pdns-dev/attachments/20081105/f5a28a74/pdns_multi_results_support.bin
More information about the Pdns-dev
mailing list