A.4. Generic PgSQL backend

PostgreSQL backend with easily configurable SQL statements, allowing you to graft PDNS on any PostgreSQL database of your choosing. Because all database schemas will be different, a generic backend is needed.

The template queries are expanded using the C function 'snprintf' which implies that substitutions are performed on the basis of %-place holders. To place a a % in a query which will not be substituted, use %%.

A.4.1. Basic functionality

To configure this backend for native operation, 9 SQL queries need to be specified which are all very similar. 4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default, 1 is needed for zone transfers.

The 4+4 regular queries must return the following 6 fields, in this exact order:

Please note that the names of the fields are not relevant, but the order is!

As said earlier, there are 8 SQL queries for regular lookups. If so called 'MBOXFW' fancy records are not used, four remain:

basic-query

Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' This is the most used query, needed for doing 1:1 lookups of qtype/name values. First %s is replaced by the ASCII representation of the qtype of the question, the second by the name.

id-query

Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' and id=%d Used for doing lookups within a domain. First %s is replaced by the qtype, the %d which should appear after the %s by the numeric domain_id.

any-query

For doing ANY queries. Also used internally. Default: select content,ttl,prio,type,domain_id,name from records where name='%s' The %s is replaced by the qname of the question.

any-id-query

For doing ANY queries within a domain. Also used internally. Default: select content,ttl,prio,type,domain_id,name from records where name='%s' and domain_id=%d The %s is replaced by the name of the domain, the %d by the numerical domain id.

A.4.2. Listing a zone

The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally:

A.4.3. Fancy records

If PDNS is used with so called 'Fancy Records', the 'MBOXFW' record exists which specifies an email address forwarding instruction, wildcard queries are sometimes needed. This is not enabled by default. A wildcard query is an internal concept - it has no relation to *.domain-type lookups. You can safely leave these queries blank.

A.4.4. Native operation schema

The default queries correspond to the following database schema:

CREATE TABLE records (
        id              SERIAL PRIMARY KEY,
        domain_id       INT DEFAULT NULL,
        name            VARCHAR(255) DEFAULT NULL,
        type            VARCHAR(6) DEFAULT NULL,
        content         VARCHAR(255) DEFAULT NULL,
        ttl             INT DEFAULT NULL,
        prio            INT DEFAULT NULL,
        change_data     INT DEFAULT NULL);

CREATE INDEX name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
GRANT SELECT ON records TO pdns;
GRANT SELECT ON records_id_seq TO pdns;
	  

A.4.5. Settings and specifying queries

The queries above are specified in pdns.conf. For example, the basic-query would appear as:

	    gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'
	  
Queries can span multiple lines, like this:
	    gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \
	    where qtype='%s' and name='%s'
	  
Do not wrap statements in quotes as this will not work. Besides the query related settings, the following configuration options are available:

gpgsql-dbname

Database name to connect to

gpgsql-host

Database host to connect to. WARNING: When specified as a hostname a chicken/egg situation might arise where the database is needed to resolve the IP address of the database. It is best to supply an IP address of the database here.

gpgsql-password

Password to connect with

gpgsql-user

PgSQL user to connect as

A.4.6. Slave operation

The PostgreSQL backend is fully slave capable. The default queries expect the following schema:

create table domains (
 id		 SERIAL PRIMARY KEY,
 name		 VARCHAR(255) NOT NULL,
 master		 VARCHAR(20) NOT NULL,
 last_check	 INT DEFAULT NULL,
 type		 VARCHAR(6) NOT NULL,
 account         VARCHAR(40) DEFAULT NULL
);
CREATE INDEX name_index ON domains(name);
GRANT UPDATE ON domains TO pdns;
GRANT SELECT ON domains_id_seq TO pdns;
  
CREATE TABLE records (
        id              SERIAL PRIMARY KEY,
        domain_id       INT DEFAULT NULL,
        name            VARCHAR(255) DEFAULT NULL,
        type            VARCHAR(6) DEFAULT NULL,
        content         VARCHAR(255) DEFAULT NULL,
        ttl             INT DEFAULT NULL,
        prio            INT DEFAULT NULL,
        change_data     INT DEFAULT NULL, 
        CONSTRAINT domain_exists 
        FOREIGN KEY(domain_id) REFERENCES domains(id)
        ON DELETE CASCADE
);

CREATE INDEX name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);

GRANT ALL ON records TO pdns;
GRANT ALL ON records_id_seq TO pdns;
      

To become a slave of the 'powerdns.com' domain, execute this:

	    insert into domains (name,master,type) values ('powerdns.com','213.244.168.217','SLAVE');
	  
And wait awhile for PDNS to pick up the addition - which happens within one minute. Typical output is:
	    Apr 09 13:34:29 All slave domains are fresh
	    Apr 09 13:35:29 1 slave domain needs checking
	    Apr 09 13:35:29 Domain powerdns.com is stale, master serial 1, our serial 0
	    Apr 09 13:35:30 [gPgSQLBackend] Connecting to database with connect string 'dbname=pdns user=pdns'
	    Apr 09 13:35:30 AXFR started for 'powerdns.com'
	    Apr 09 13:35:30 AXFR done for 'powerdns.com'
	    Apr 09 13:35:30 [gPgSQLBackend] Closing connection
	  

A.4.7. Superslave tables

To enable this feature in the Generic PostgreSQL backend, issue the following:

	    create table supermasters (ip VARCHAR(25), nameserver VARCHAR(255), account VARCHAR(40));
	    GRANT SELECT ON supermasters TO pdns;
	    GRANT ALL ON domains TO pdns;
	    GRANT ALL ON domains_id_seq TO pdns;
	  

To configure a supermaster with IP address 10.0.0.11 which lists this installation as 'autoslave.powerdns.com', issue the following:

	    insert into supermasters ('10.0.0.11','autoslave.powerdns.com','internal');
	  
From now on, valid notifies from 10.0.0.11 that list a NS record containing 'autoslave.powerdns.com' will lead to the provisioning of a slave domain under the account 'internal'.

WARNING: as of 1.99.9 this feature is new and relatively untested. Only works with the PostgreSQL backend.