+++ /dev/null
-# Generic MySQL and PostgreSQL backends
-| | |
-|:--|:--|
-|Native|Yes|
-|Master|Yes|
-|Slave|Yes|
-|Superslave|Yes|
-|Autoserial|Yes (v3.1 and up)|
-|Case|All lower|
-|DNSSEC|Yes (set `gmysql-dnssec` or `gpgsql-dnssec`)|
-|Disabled data|Yes (v3.4.0 and up)|
-|Comments|Yes (v3.4.0 and up)|
-|Module name < 2.9.3|pgmysql|
-|Module name > 2.9.2|gmysql and gpgsql|
-|Launch name| gmysql and gpgsql2 and gpgsql|
-
-PostgreSQL and MySQL backend with easily configurable SQL statements, allowing you to graft PowerDNS on any PostgreSQL or MySQL database of your choosing. Because all database schemas will be different, a generic backend is needed to cover all needs.
-
-**Warning**: Host names and the MNAME of a SOA records are NEVER terminated with a '.' in PowerDNS storage! If a trailing '.' is present it will inevitably cause problems, problems that may be hard to debug.
-
-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 % in a query which will not be substituted, use %%. Make sure to fill out the search key, often called 'name' in lower case!
-
-There are in fact two backends, one for PostgreSQL and one for MySQL but they accept the same settings and use almost exactly the same database schema.
-
-# MySQL specifics
-
-**Warning**: If using MySQL with 'slave' support enabled in PowerDNS you **must** run MySQL with a table engine that supports transactions.
-
-In practice, great results are achieved with the 'InnoDB' tables. PowerDNS will silently function with non-transaction aware MySQLs but at one point this is going to harm your database, for example when an incoming zone transfer fails.
-
-**Warning**: For MySQL 5.1.11 and earlier, and for MySQL 5.1.29 and later the default binary logging format is STATEMENT which is nondeterministic and can cause differences in data between master and slave. See ["5.2.4.2, Setting The Binary Log Format"](http://dev.mysql.com/doc/refman/5.7/en/binary-log-setting.html) for more information.
-
-The default setup conforms to the following schema:
-
-```
-!!include=../modules/gmysqlbackend/schema.mysql.sql
-```
-
-`zone2sql` with the `--gmysql` flag also assumes this layout is in place.
-
-For full migration notes, please see [Migration](migration.md).
-
-This schema contains all elements needed for master, slave and superslave operation.
-
-When using the InnoDB storage engine, we suggest adding the following lines to the 'create table records' command above:
-
-```
-CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `domains`
-(`id`) ON DELETE CASCADE
-```
-
-Or, if you have already created the tables, execute:
-
-```
-ALTER TABLE `records` ADD CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`)
-REFERENCES `domains` (`id`) ON DELETE CASCADE;
-```
-
-This automates deletion of records on deletion of a domain from the domains table.
-
-# PostgreSQL specifics
-
-The default setup conforms to the following schema, which you should add to a PostgreSQL database.
-
-```
-!!include=../modules/gpgsqlbackend/schema.pgsql.sql
-```
-
-`zone2sql` with the `--gpgsql` flag also assumes this layout is in place.
-
-This schema contains all elements needed for master, slave and superslave operation.
-
-For full migration notes, please see [Migration](migration.md).
-
-With PostgreSQL, you may have to run `createdb powerdns` first and then connect to that database with `psql powerdns`, and feed it the schema above.
-
-# Oracle specifics
-Generic Oracle support is only available since version 2.9.18. The default setup conforms to the following schema, which you should add to an Oracle database. You may need or want to add `namespace` statements.
-
-```
-!!include=../modules/gpgsqlbackend/schema.pgsql.sql
-```
-
-This schema contains all elements needed for master, slave and superslave operation.
-
-Inserting records is a bit different compared to MySQL and PostgreSQL, you should use:
-
-```
-INSERT INTO domains (id,name,type) VALUES (domains_id_sequence.nextval, 'example.net', 'NATIVE');
-```
-
-Furthermore, use the `goracle-tnsname` setting to specify which TNSNAME the Generic Oracle Backend should be connecting to. There are no `goracle-dbname`, `goracle-host` or `goracle-port` settings, their equivalent is in `/etc/tnsnames.ora`.
-
-# Basic functionality
-4 queries are needed for regular lookups and 1 is needed for zone transfers.
-
-The 4+4 regular queries must return the following 6 fields, in this exact order:
-
-* content: This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example.
-* ttl: TTL of this record, in seconds. Must be a real value, no checking is performed.
-* prio: For MX records, this should be the priority of the mail exchanger specified.
-* qtype: The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this field returns an exact answer - PowerDNS won't recognise 'A ' as 'A'. This can be achieved by using a VARCHAR instead of a CHAR.
-* domain\_id: Each domain must have a unique domain\_id. No two domains may share a domain\_id, all records in a domain should have the same. A number.
-* name: Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain!
-* disabled: If set to true, this record is hidden from DNS clients, but can still be modified from the REST API. See [Disabled data](#disabled-data). (Available since version 3.4.0.)
-
-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. To configure them, set `gmysql-basic-query` or `gpgsql-basic-query`, depending on your choice of backend.
-
-# Queries and settings
-## Regular Queries
-### `basic-query`
-Default: `select content,ttl,prio,type,domain_id,disabled,name,auth from records where type='%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,disabled,name,auth from records where type='%s' and name='%s' and domain_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,disabled,name,auth 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,disabled,name,auth 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.
-
-The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally:
-
-### `list-query`
-To list an entire zone. Default: `select content,ttl,prio,type,domain_id,disabled,name,auth from records where (disabled=0 OR %d) AND domain_id=%d` The first %d is replaced by the "include disabled" flag (default 0), the second %d is replaced by the domain_id.
-
-## DNSSEC queries
-If DNSSEC is enabled (through the `-dnssec` flag on a gsql backend), many queries are replaced by slightly extended variants that also query the auth column. The auth column is always added as the rightmost column. These are the -auth defaults:
-
-### `basic-query-auth`
-Basic query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name='%s'`
-
-### `id-query-auth`
-Basic with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name='%s' and domain_id=%d`
-
-### `wildcard-query-auth`
-Wildcard query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name like '%s'`
-
-### `wildcard-id-query-auth`
-Wildcard with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name like '%s' and domain_id='%d'`
-
-### `any-query-auth`
-Any query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name='%s'`
-
-### `any-id-query-auth`
-Any with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name='%s' and domain_id=%d`
-
-### `wildcard-any-query-auth`
-Wildcard ANY query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name like '%s'`
-
-### `wildcard-any-id-query-auth`
-Wildcard ANY with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name like '%s' and domain_id='%d'`
-
-### `list-query-auth`
-AXFR query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where domain_id='%d' order by name, type`
-
-Additionally, there are some new queries to determine NSEC(3) order:
-
-### `get-order-first-query`
-DNSSEC Ordering Query, first. Default: `select ordername, name from records where domain_id=%d and ordername is not null order by 1 asc limit 1`
-
-### `get-order-before-query`
-DNSSEC Ordering Query, before. Default: `select ordername, name from records where ordername <= '%s' and domain_id=%d and ordername is not null order by 1 desc limit 1`
-
-### `get-order-after-query`
-DNSSEC Ordering Query, after. Default: `select min(ordername) from records where ordername > '%s' and domain_id=%d and ordername is not null`
-
-### `get-order-last-query`
-DNSSEC Ordering Query, last. Default: `select ordername, name from records where ordername != '' and domain_id=%d and ordername is not null order by 1 desc limit 1`
-
-Finally, these two queries are used to set ordername and auth correctly in a database:
-
-### `set-order-and-auth-query`
-DNSSEC set ordering query. Default: `update records set ordername='%s',auth=%d where name='%s' and domain_id='%d'`
-
-### `nullify-ordername-and-auth-query`
-DNSSEC nullify ordername query. Default: `update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'`
-
-Make sure to read [Rules for filling out fields in database backends](dnssec.md#rules-for-filling-out-fields-in-database-backends) if you wish to calculate ordername and auth without using pdns-rectify.
-
-## Master/slave queries
-Most installations will have zero need to change the following settings, but should the need arise, here they are:
-
-### `master-zone-query`
-Called to determine the master of a zone. Default: `select master from domains where name='%s' and type='SLAVE'`
-
-### `info-zone-query`
-Called to retrieve (nearly) all information for a domain: Default: `select id,name,master,last_check,notified_serial,type from domains where name='%s'`
-
-### `info-all-slaves-query`
-Called to retrieve all slave domains Default: `select id,name,master,last_check,type from domains where type='SLAVE'`
-
-### `supermaster-query`
-Called to determine if a certain host is a supermaster for a certain domain name. Default: `select account from supermasters where ip='%s' and nameserver='%s';`
-
-### `insert-slave-query`
-Called to add a domain as slave after a supermaster notification. Default: `insert into domains (type,name,master,account) values('SLAVE','%s','%s','%s')`
-
-### `insert-record-query`
-Called during incoming AXFR. Default: `insert into records (content,ttl,prio,type,domain_id,name) values ('%s',%d,%d,'%s',%d,'%s')`
-
-### `update-serial-query`
-Called to update the last notified serial of a master domain. Default: `update domains set notified_serial=%d where id=%d`
-
-### `update-lastcheck-query`
-Called to update the last time a slave domain was successfully checked for freshness. Default: `update domains set last_check=%d where id=%d`
-
-### `info-all-master-query`
-Called to get data on all domains for which the server is master. Default: `select id,name,master,last_check,notified_serial,type from domains where type='MASTER'`
-
-### `delete-zone-query`
-Called to delete all records of a zone. Used before an incoming AXFR. Default: `delete from records where domain_id=%d`
-
-## Comment queries
-For listing/modifying comments. For defaults, please see `pdns_server --load=BACKEND --config`.
-
-### `list-comments-query`
-Called to get all comments in a zone. Returns fields: domain\_id, name, type, modified\_at, account, comment.
-
-### `insert-comment-query`
-Called to create a single comment for a specific RRSet. Given fields: domain\_id, name, type, modified\_at, account, comment
-
-### `delete-comment-rrset-query`
-Called to delete all comments for a specific RRset. Given fields: domain\_id, name, type
-
-### `delete-comments-query`
-Called to delete all comments for a zone. Usually called before deleting the entire zone. Given fields: domain\_id
-
-### `wildcard-query`
-Can be left blank. See above for an explanation. Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name like '%s'`
-
-### `wildcard-id-query`
-Can be left blank. See above for an explanation. Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name like '%s' and domain_id=%d` Used for doing lookups within a domain.
-
-### `wildcard-any-query`
-For doing wildcard ANY queries. Default: `select content,ttl,prio,type,domain_id,name from records where name like '%s'`
-
-### `wildcard-any-id-query`
-For doing wildcard ANY queries within a domain. Default: `select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d`
-
-## 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,disabled,name,auth from records where type='%s' and name='%s'
-```
-
-When using the Generic PostgreSQL backend, they appear as above. When using the generic MySQL backend, change the "gpgsql-" prefix to "gmysql-".
-
-Queries can span multiple lines, like this:
-
-```
-gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \
-where type='%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, where one should substitute `gmysql`, `gpgsql`, or `goracle` for the prefix `backend`. So `backend-dbname` can stand for `gpgsql-dbname` or `gmysql-dbname` etc.
-
-### `backend-dbname`
-Database name to connect to
-
-### `backend-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.
-
-**Only for PostgreSQL**: If host begins with a slash, it specifies Unix-domain communication rather than TCP/IP communication; the value is the name of the directory in which the socket file is stored.
-
-### `backend-port`
-Database port to connect to.
-
-### gmysql-socket (only for MySQL!)
-File name where the MySQL connection socket resides. Often `/tmp/mysql.sock` or `/var/run/mysqld/mysqld.sock`.
-
-### `backend-password`
-Database password to connect with.
-
-### `backend-user`
-Database user to connect as.
-
-### `backend-group` (MySQL only, since 3.2)
-MySQL "group" to connect as, defaults to "client".
-
-## Native operation
-To add a domain, issue the following:
-
-```
-INSERT INTO domains (name, type) VALUES ('powerdns.com', 'NATIVE');
-```
-
-The records table can now be filled by with the domain\_id set to the id of the domains table row just inserted.
-
-## Slave operation
-These backends are fully slave capable. To become a slave of the 'example.com' domain, execute this:
-
-```
-INSERT INTO domains (name, master, type) VALUES ('example.com', '198.51.100.6', 'SLAVE');
-```
-
-And wait a while for PowerDNS to pick up the addition - which happens within one minute. There is no need to inform PowerDNS that a new domain was added. 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] Connected to database
-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
-```
-
-From now on, PowerDNS is authoritative for the 'powerdns.com' zone and will respond accordingly for queries within that zone.
-
-Periodically, PowerDNS schedules checks to see if domains are still fresh. The default [`slave-cycle-interval`](settings.md#slave-cycle-interval) is 60 seconds, large installations may need to raise this value. Once a domain has been checked, it will not be checked before its SOA refresh timer has expired. Domains whose status is unknown get checked every 60 seconds by default.
-
-## Superslave operation
-To configure a supermaster with IP address 203.0.113.53 which lists this installation as 'autoslave.example.com', issue the following:
-
-```
-INSERT INTO supermasters VALUES ('203.0.113.53', 'autoslave.example.com', 'internal');
-```
-
-From now on, valid notifies from 203.0.113.53 that list a NS record containing 'autoslave.example.com' will lead to the provisioning of a slave domain under the account 'internal'. See [Supermaster](modes-of-operation.md#supermaster-automatic-provisioning-of-slaves) for details.
-
-## Master operation
-The PostgreSQL backend is fully master capable with automatic discovery of serial changes. Raising the serial number of a domain suffices to trigger PowerDNS to send out notifications. To configure a domain for master operation instead of the default native replication, issue:
-
-```
-INSERT INTO domains (name, type) VALUES ('powerdns.com', 'MASTER');
-```
-
-Make sure that the assigned id in the domains table matches the domain\_id field in the records table!
-
-## Disabled data
-PowerDNS understands the notion of disabled records. They are marked by setting "disabled" to `1` (for PostgreSQL: `true`). By extension, when the SOA record for a domain is disabled, the entire domain is considered to be disabled.
-
-Effects: the record (or domain, respectively) will not be visible to DNS clients. The REST API will still see the record (or domain). Even if a domain is disabled, slaving still works. Slaving considers a disabled domain to have a serial of 0; this implies that a slaved domain will not stay disabled.
--- /dev/null
+# Generic MySQL backend
+| | |
+|:--|:--|
+|Native|Yes|
+|Master|Yes|
+|Slave|Yes|
+|Superslave|Yes|
+|Autoserial|Yes (v3.1 and up)|
+|Case|All lower|
+|DNSSEC|Yes (set `gmysql-dnssec`)|
+|Disabled data|Yes (v3.4.0 and up)|
+|Comments|Yes (v3.4.0 and up)|
+|Module name | gmysql|
+|Launch name| gmysql|
+
+**warning**: If using MySQL with 'slave' support enabled in PowerDNS you **must**
+run MySQL with a table engine that supports transactions.
+In practice, great results are achieved with the 'InnoDB' tables. PowerDNS will
+silently function with non-transaction aware MySQLs but at one point this is
+going to harm your database, for example when an incoming zone transfer fails.
+
+The default schema is included at the bottom of this page. [`zone2sql`](migration.md#zone2sql)
+with the `--gmysql` flag also assumes this layout is in place. For full migration
+notes, please see [Migration](migration.md). This schema contains all elements
+needed for master, slave and superslave operation.
+
+When using the InnoDB storage engine, we suggest adding the following lines to
+the 'create table records' command above:
+
+```
+CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `domains`
+(`id`) ON DELETE CASCADE
+```
+
+Or, if you have already created the tables, execute:
+
+```
+ALTER TABLE `records` ADD CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`)
+REFERENCES `domains` (`id`) ON DELETE CASCADE;
+```
+
+This automates deletion of records on deletion of a domain from the domains table.
+
+# Using MySQL replication
+To support `NATIVE` domains, the `binlog_format` for the MySQL replication **must**
+be set to `MIXED` or `ROW` to prevent differences in data between replicated
+servers. See ["5.2.4.2, Setting The Binary Log Format"](http://dev.mysql.com/doc/refman/5.7/en/binary-log-setting.html)
+for more information.
+
+# Settings
+## `gmysql-host`
+Host (ip address) to connect to. Mutually exclusive with [`gmysql-socket`](#gmysql-socket).
+
+**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.
+
+## `gmysql-port`
+The port to connect to on [`gmysql-host`](#gmysql-host). Default: 3306
+
+## `gmysql-socket`
+Connect to the UNIX socket at this path. Mutually exclusive with [`gmysql-host`](#gmysql-host).
+
+## `gmysql-dbname`
+Name of the database to connect to. Default: "pdns".
+
+## `gmysql-user`
+User to connect as. Default: "powerdns".
+
+## `gmysql-group`
+Group to connect as. Default: "client".
+
+## `gmysql-password`
+The password to for [`gmysql-user`](#gmysql-user).
+
+## `gmysql-dnssec`
+Enable DNSSEC processing for this backend. Default=no.
+
+## `gmysql-innodb-read-committed`
+Use the InnoDB READ-COMMITTED transaction isolation level. Default=yes.
+
+# Default Schema
+```
+!!include=../modules/gmysqlbackend/schema.mysql.sql
+```
--- /dev/null
+# Generic Oracle backend
+| | |
+|:--|:--|
+|Native|Yes|
+|Master|Yes|
+|Slave|Yes|
+|Superslave|Yes|
+|Autoserial|Yes (v3.1 and up)|
+|Case|All lower|
+|DNSSEC|Yes (set `goracle-dnssec`)|
+|Disabled data|Yes (v3.4.0 and up)|
+|Comments|Yes (v3.4.0 and up)|
+|Module name | goracle|
+|Launch name| goracle|
+
+The Generic Oracle Backend is a [Generic SQL backend](backend-generic-sql.md).
+The default setup conforms to the following schema, which you should add to an
+Oracle database. You may need or want to add `namespace` statements.
+
+```
+!!include=../modules/goraclebackend/schema.goracle.sql
+```
+
+This schema contains all elements needed for master, slave and superslave operation.
+
+Inserting records is a bit different compared to MySQL and PostgreSQL, you should use:
+
+```
+INSERT INTO domains (id,name,type) VALUES (domains_id_sequence.nextval, 'example.net', 'NATIVE');
+```
+
+# Settings
+## `goracle-tnsname`
+Which TNSNAME the Generic Oracle Backend should be connecting to. There are no
+`goracle-dbname`, `goracle-host` or `goracle-port` settings, their equivalent is
+in `/etc/tnsnames.ora`.
+
+## `goracle-dnssec`
+Enable DNSSEC processing for this backend. Default=no.
--- /dev/null
+# Generic PostgreSQL backend
+| | |
+|:--|:--|
+|Native|Yes|
+|Master|Yes|
+|Slave|Yes|
+|Superslave|Yes|
+|Autoserial|Yes (v3.1 and up)|
+|Case|All lower|
+|DNSSEC|Yes (set `gpgsql-dnssec`)|
+|Disabled data|Yes (v3.4.0 and up)|
+|Comments|Yes (v3.4.0 and up)|
+|Module name | pgsql|
+|Launch name| pgsql|
+
+This PostgreSQL backend is based on the [generic SQL backend](backend-generic-sql.md).
+The default setup conforms to the schema at the bottom of this page, note that
+[`zone2sql`](migration.md#zone2sql) with the `--gpgsql` flag also assumes this layout is in place.
+
+This schema contains all elements needed for master, slave and superslave operation.
+For full migration notes, please see [Migration](migration.md).
+
+With PostgreSQL, you may have to run `createdb pdns` first and then connect
+to that database with `psql pdns`, and feed it the schema above.
+
+# Settings
+## `gpgsql-host`
+Host (ip address) to connect to. If `pgsql-host` begins with a slash, it
+specifies Unix-domain communication rather than TCP/IP communication; the value
+is the name of the directory in which the socket file is stored.
+
+**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-port`
+The port to connect to on [`gpgsql-host`](#gpgsql-host). Default: 5432
+
+## `gpgsql-dbname`
+Name of the database to connect to. Default: "pdns".
+
+## `gpgsql-user`
+User to connect as. Default: "powerdns".
+
+## `gpgsql-password`
+The password to for [`gpgsql-user`](#gpgsql-user).
+
+## `gpgsql-dnssec`
+Enable DNSSEC processing for this backend. Default=no.
+
+# Default schema
+```
+!!include=../modules/gpgsqlbackend/schema.pgsql.sql
+```
+
--- /dev/null
+# Generic SQL Backends
+The generic SQL backends (like gmysql, gpgsql and godbc) are backends with easily
+configurable SQL statements, allowing you to graft PowerDNS on any SQL database
+of your choosing. Because all database schemas will be different, a generic
+backend is needed to cover all needs.
+
+**Warning**: Host names and the MNAME of a SOA records are NEVER terminated with
+a '.' in PowerDNS storage! If a trailing '.' is present it will inevitably cause
+problems, problems that may be hard to debug.
+
+# Basic functionality
+All domains in the generic SQL backends have a 'type' field that describes the
+[mode of operation](modes-of-operation.md).
+
+## Native operation
+To add a domain, issue the following:
+
+```
+INSERT INTO domains (name, type) VALUES ('powerdns.com', 'NATIVE');
+```
+
+The records table can now be filled by with the domain\_id set to the id of the domains table row just inserted.
+
+## Slave operation
+These backends are fully slave capable. To become a slave of the 'example.com' domain, execute this:
+
+```
+INSERT INTO domains (name, master, type) VALUES ('example.com', '198.51.100.6', 'SLAVE');
+```
+
+And wait a while for PowerDNS to pick up the addition - which happens within one
+minute (this is determined by the [`slave-cycle-interval`](settings.md#slave-cycle-interval)
+setting). There is no need to inform PowerDNS that a new domain was added.
+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] Connected to database
+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
+```
+
+From now on, PowerDNS is authoritative for the 'powerdns.com' zone and will
+respond accordingly for queries within that zone.
+
+Periodically, PowerDNS schedules checks to see if domains are still fresh.
+The default [`slave-cycle-interval`](settings.md#slave-cycle-interval) is 60 seconds,
+large installations may need to raise this value. Once a domain has been checked,
+it will not be checked before its SOA refresh timer has expired. Domains whose
+status is unknown get checked every 60 seconds by default.
+
+## Superslave operation
+To configure a supermaster with IP address 203.0.113.53 which lists this
+installation as 'autoslave.example.com', issue the following:
+
+```
+INSERT INTO supermasters VALUES ('203.0.113.53', 'autoslave.example.com', 'internal');
+```
+
+From now on, valid notifies from 203.0.113.53 that list a NS record containing
+'autoslave.example.com' will lead to the provisioning of a slave domain under
+the account 'internal'. See [Supermaster](modes-of-operation.md#supermaster-automatic-provisioning-of-slaves)
+for details.
+
+## Master operation
+The generic SQL backend is fully master capable with automatic discovery of serial
+changes. Raising the serial number of a domain suffices to trigger PowerDNS to
+send out notifications. To configure a domain for master operation instead of
+the default native replication, issue:
+
+```
+INSERT INTO domains (name, type) VALUES ('powerdns.com', 'MASTER');
+```
+
+Make sure that the assigned id in the domains table matches the domain\_id field
+in the records table!
+
+## Disabled data
+PowerDNS understands the notion of disabled records. They are marked by setting
+"disabled" to `1` (for PostgreSQL: `true`). By extension, when the SOA record for
+a domain is disabled, the entire domain is considered to be disabled.
+
+Effects: the record (or domain, respectively) will not be visible to DNS clients.
+The REST API will still see the record (or domain). Even if a domain is disabled,
+slaving still works. Slaving considers a disabled domain to have a serial of 0;
+this implies that a slaved domain will not stay disabled.
+
+# Queries
+From version 4.0.0 onward, the generic SQL backends use prepared statements for
+their queries. Before 4.0.0, queries were expanded using the C function 'snprintf'
+which implies that substitutions are performed on the basis of %-placeholders.
+
+To see the default queries for a backend, run
+`pdns_server --no-config --launch=BACKEND --config`.
+
+## Regular Queries
+For regular operation, several queries are used for record-lookup. These queries
+must return the following fields in order:
+
+- content: This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example.
+- ttl: TTL of this record, in seconds. Must be a positive integer, no checking is performed.
+- prio: For MX and SRV records, this should be the priority of the record specified.
+- qtype: The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this field returns an exact answer - PowerDNS won't recognise 'A ' as 'A'. This can be achieved by using a VARCHAR instead of a CHAR.
+- domain\_id: Unique identifier for this domain. This id must be unique across all backends. Must be a positive integer.
+- name: Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain!
+- disabled: Boolean, if set to true, this record is hidden from DNS clients, but can still be modified from the REST API. See [Disabled data](#disabled-data). (Available since version 3.4.0.)
+- auth: A boolean describing if PowerDNS is authoritative for this record (DNSSEC)
+
+Please note that the names of the fields are not relevant, but the order is!
+
+- `basic-query`: This is the most used query, needed for doing 1:1 lookups of qtype/name values.
+- `id-query`: Used for doing lookups within a domain.
+- `any-query`: For doing ANY queries. Also used internally.
+- `any-id-query`: For doing ANY queries within a domain. Also used internally.
+- `list-query`: For doing AXFRs, lists all records in the zone. Also used internally.
+- `list-subzone-query`: For doing RFC 2136 DNS Updates, lists all records below a zone.
+- `search-records-query`: To search for records on name and content.
+
+## DNSSEC queries
+These queries are used by e.g. `pdnsutil rectify-zone`. Make sure to read
+[Rules for filling out fields in database backends](dnssec.md#rules-for-filling-out-fields-in-database-backends)
+if you wish to calculate ordername and auth without using pdns-rectify.
+
+- `insert-ent-query`: Insert empty non-terminal in zone.
+- `insert-empty-non-terminal-query`: Insert empty non-terminal in zone.
+- `insert-ent-order-query`: Insert empty non-terminal in zone with the ordername set.
+- `delete-empty-non-terminal-query`: Delete an empty non-terminal in a zone.
+- `remove-empty-non-terminals-from-zone-query`: remove all empty non-terminals from zone.
+
+- `get-order-first-query`: DNSSEC Ordering Query, first.
+- `get-order-before-query`: DNSSEC Ordering Query, before.
+- `get-order-after-query`: DNSSEC Ordering Query, after.
+- `get-order-last-query`: DNSSEC Ordering Query, last.
+- `update-ordername-and-auth-query`: DNSSEC update ordername and auth for a qname query.
+- `update-ordername-and-auth-type-query`: DNSSEC update ordername and auth for a rrset query.
+- `nullify-ordername-and-update-auth-query`: DNSSEC nullify ordername and update auth for a qname query.
+- `nullify-ordername-and-update-auth-type-query`: DNSSEC nullify ordername and update auth for a rrset query.
+
+## Domain and zone manipulation
+
+- `insert-zone-query`: Add a new NATIVE domain.
+- `update-kind-query`: Called to update the type of domain.
+- `delete-zone-query` Called to delete all records of a zone. Used before an incoming AXFR.
+- `delete-domain-query`: Called to delete a domain from the domains-table.
+
+- `get-all-domains-query`: Used to get information on all active domains.
+- `info-zone-query`: Called to retrieve (nearly) all information for a domain.
+
+- `insert-record-query`: Called during incoming AXFR.
+- `insert-record-order-query`: Add a new record for a domain, including the ordername.
+- `update-account-query`: Set the account for a domain.
+- `delete-names-query`: Called to delete all records of a certain name.
+- `delete-rrset-query`: Called to delete an RRset based on domain\_id, name and type.
+
+- `get-all-domain-metadata-query`: Get all [`domain metadata`](domainmetadata.md) for a domain.
+- `get-domain-metadata-query`: Get a single piece of [`domain metadata`](domainmetadata.md).
+- `clear-domain-metadata-query`: Delete a single entry of domain metadata.
+- `clear-domain-all-metadata-query`: Remove all domain metadata for a domain.
+- `set-domain-metadata-query`: Add domain metadata for a zone.
+
+- `add-domain-key-query`: Called to a cryptokey to a domain.
+- `list-domain-keys-query`: Called to get all cryptokeys for a domain.
+- `activate-domain-key-query`: Called to set a cryptokey to active.
+- `deactivate-domain-key-query`: Called to set a cryptokey to inactive.
+- `clear-domain-all-keys-query`: Called to remove all DNSSEC keys for a zone.
+- `remove-domain-key-query`: Called to remove a crypto key.
+
+## Master/slave queries
+These queries are used to manipulate the master/slave information in the database.
+Most installations will have zero need to change the following queries.
+
+### On masters
+- `info-all-master-query`: Called to get data on all domains for which the server is master.
+- `update-serial-query` Called to update the last notified serial of a master domain.
+- `zone-lastchange-query`: Called to determine the last change to a zone, used for autoserial.
+
+### On slaves
+- `info-all-slaves-query`: Called to retrieve all slave domains.
+- `insert-slave-query`: Called to add a domain as slave after a supermaster notification.
+- `master-zone-query`: Called to determine the master of a zone.
+- `update-lastcheck-query`: Called to update the last time a slave domain was successfully checked for freshness.
+- `update-master-query`: Called to update the master address of a domain.
+
+### On superslaves
+- `supermaster-query`: Called to determine if a certain host is a supermaster for a certain domain name.
+- `supermaster-name-to-ips`: Called to the IP and account for a supermaster.
+
+## TSIG
+- `get-tsig-key-query`: Called to get the algorithm and secret from a named TSIG key.
+- `get-tsig-keys-query`: Called to get all TSIG keys.
+- `set-tsig-key-query`: Called to set the algorithm and secret for a named TSIG key.
+- `delete-tsig-key-query`: Called to delete a named TSIG key.
+
+## Comment queries
+For listing/modifying comments.
+
+- `list-comments-query`: Called to get all comments in a zone. Returns fields: domain\_id, name, type, modified\_at, account, comment.
+- `insert-comment-query` Called to create a single comment for a specific RRSet. Given fields: domain\_id, name, type, modified\_at, account, comment
+- `delete-comment-rrset-query`: Called to delete all comments for a specific RRset. Given fields: domain\_id, name, type
+- `delete-comments-query`: Called to delete all comments for a zone. Usually called before deleting the entire zone. Given fields: domain\_id
+- `search-comments-query`: Called to search for comment by name or content.
+
+## Specifying queries
+The queries above are specified in pdns.conf. For example, the basic-query for
+the Generic MySQL backend would appear as:
+
+```
+gmysql-basic-query=SELECT content,ttl,prio,type,domain_id,disabled,name,auth FROM records WHERE disabled=0 and type=? and name=?
+```
+
+Queries can span multiple lines, like this:
+
+```
+gmysql-basic-query=SELECT content,ttl,prio,type,domain_id,disabled,name,auth \
+FROM records WHERE disabled=0 and type=? and name=?
+```
As this is a generic backend, built on top of the gSql framework, you can
specify all queries as documented in
-[Generic MySQL and PostgreSQL backends](backend-generic-mypgsql.md#queries-and-settings).
+[Generic SQL Backends](backend-generic-sql.md#queries).
SQLite exists in two incompatible versions, PowerDNS only supports version 3. To
launch the backend, put `launch=gsqlite3` in the configuration.
The implementation requires the backend to support a number of new oparations. Currently, the following backends have been modified to support DNS update:
-* [gmysql](backend-generic-mypgsql.md)
-* [gpgsql](backend-generic-mypgsql.md)
-* [gsqlite3](backend-gsqlite.md)
+* [gmysql](backend-generic-mysql.md)
+* [gpgsql](backend-generic-postgresql.md)
+* [gsqlite3](backend-generic-sqlite.md)
+* [goracle](backend-generic-oracle.md)
+* [godbc](backend-generic-odbc.md)
# Configuration options
There are two configuration parameters that can be used within the powerdns configuration file.
| Name | Status | Native | Master | Slave | Superslave | Autoserial | DNSSEC | Disabled Data | Comments | Launch Name |
|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|
| [BIND](backend-bind.md) | Supported | Yes | Yes | Yes | Experimental | No | Yes | No | No | `bind` |
+| [Generic MySQL](backend-generic-mysql.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gmysql` |
+| [Generic ODBC](backend-generic-odbc.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes| `godbc` |
+| [Generic Oracle](backend-generic-oracle.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `goracle` |
+| [Generic PostgreSQL](backend-generic-postgresql.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gpgsql` |
+| [Generic SQLite 3](backend-generic-sqlite.md) 3 | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gsqlite3` |
| [GeoIP](backend-geoip.md) | Supported | Yes | No | No | No | No | Yes | No | No | `geoip` |
| [LDAP](backend-ldap.md) | Unmaintained | Yes | No | No | No | No | No | Unknown (No) | Unknown (No) | Unknown |
-| [MySQL](backend-generic-mypgsql.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gmysql` |
| [MyDNS](backend-mydns.md) | Supported | Yes | No | No | No | No | No | No | No | `mydns` |
-| [ODBC](backend-godbc.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes| `godbc` |
| [OpenDBX](backend-opendbx.md) | Supported | Yes | Yes | Yes | Yes | Unknown (No) | No | Unknown (No) | Unknown (No) | `opendbx` |
| [Oracle](backend-oracle.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Unknown (No) | No | `oracle` |
| [Pipe](backend-pipe.md) | Supported | Yes | No | No | No | No | Partial (no delegation, no key storage) | No | No | `pipe` |
-| [PostgreSQL](backend-generic-mypgsql.md) | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gpgsql` |
| [Random](backend-random.md) | Supported | Yes | No | No | No | No | Yes (no key storage) | No | No | `random` |
| [Remote](backend-remote.md) | Supported | Yes | Yes\* | Yes\* | Yes\* | Yes\* | Yes\* | Unknown (No) | Unknown(No) | `remote` |
-| [SQLite](backend-gsqlite.md) 3 | Supported | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | `gsqlite3` |
| [TinyDNS](backend-tinydns.md) | Experimental | Yes | Yes | No | No | No | No | Unknown (No) | Unknown (No) | `tinydns` |
\*: Please read the backend-specific documentation.
Most problems involve PDNS not being able to connect to the database.
### Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
-Your MySQL installation is probably defaulting to another location for its socket. Can be resolved by figuring out this location (often `/var/run/mysqld.sock`), and specifying it in the configuration file with the [`gmysql-socket`](backend-generic-mypgsql.md#gmysql-socket) parameter.
+Your MySQL installation is probably defaulting to another location for its socket. Can be resolved by figuring out this location (often `/var/run/mysqld.sock`), and specifying it in the configuration file with the [`gmysql-socket`](backend-generic-mysql.md#gmysql-socket) parameter.
-Another solution is to not connect to the socket, but to 127.0.0.1, which can be achieved by specifying [`gmysql-host=127.0.0.1`](backend-generic-mypgsql.md#gmysql-host).
+Another solution is to not connect to the socket, but to 127.0.0.1, which can be achieved by specifying [`gmysql-host=127.0.0.1`](backend-generic-mysql.md#gmysql-host).
### Host 'x.y.z.w' is not allowed to connect to this MySQL server
These errors are generic MySQL errors. Solve them by trying to connect to your MySQL database with the MySQL console utility `mysql` with the parameters specified to PDNS. Consult the MySQL documentation.
Before migrating to PowerDNS a few things should be considered.
PowerDNS does not operate as a 'slave' or 'master' server with all backends.
-Only the [Generic SQL](backend-generic-mypgsql.md), [BIND](backend-bind.md) backends have the ability to act as master or slave.
+Only the [Generic SQL](backend-generic-sql.md), [BIND](backend-bind.md) backends have the ability to act as master or slave.
To migrate, the `zone2sql` tool is provided. There are also scripts from external contributors for migrating from `MyDNS` server. See https://github.com/PowerDNS/pdns/wiki/Migrating-DBs-FROM-MyDNS for details. There is also tool in pdnsutil to migrate using various backends, most notably bind and mydns. See below for more information.
- Added the new DNS parser logic, called MOADNSParser. Completely modular, every memory access checked.
- 'sdig', a simple dig work-alike with 'canonical' output, which is used for the regression tests. Based on the new DNS parser logic.
- **dnswasher**, **dnsreplay** and **dnsscope**, all DNS analysis tools. See [Tools to analyse DNS traffic](tools/analysis.md "Tools to analyse DNS traffic") for more details.
-- Generic Oracle Backend, sponsored by Register.COM. See [Oracle specifics](authoritative/backend-generic-mypgsql.md#goracle "Oracle specifics").
+- Generic Oracle Backend, sponsored by Register.COM. See [Oracle specifics](authoritative/backend-generic-oracle.md "Oracle specifics").
# Version 2.9.17
## New features
- --version command (requested by Mike Benoit)
- delegation-only, a Verisign special.
-- Generic [SQLite](http://www.sqlite.org) support, by Michel 'Who da man?' Stol. See [Generic SQLite backend](authoritative/backend-gsqlite.md).
+- Generic [SQLite](http://www.sqlite.org) support, by Michel 'Who da man?' Stol. See [Generic SQLite backend](authoritative/backend-generic-sqlite.md).
- init.d script for pdns\_recursor
- Recursor now actually purges its cache, saving memory.
- Slave configuration now no longer falls over when presented with a NULL master
In other news, we now have a security page at [Security](security/index.md). Furthermore, Maurice Nonnekes contributed an OpenBSD port! See [his page](http://www.codeninja.nl/openbsd/powerdns/) for more details!
## New features and improvements
-- All SQL queries in the generic backends are now available for configuration. (Martin Klebermass, Bert Hubert). See [Generic MySQL and PostgreSQL backends](authoritative/backend-generic-mypgsql.md).
+- All SQL queries in the generic backends are now available for configuration. (Martin Klebermass, Bert Hubert). See [Generic SQL backends](authoritative/backend-generic-sql.md).
- A recursing nameserver! See [PowerDNS Recursor](recursor/index.md).
- An incoming AXFR now only starts a backend zone replacement transaction after the first record arrived successfully, thus making sure no work is done when a remote nameserver is unable/unwilling to AXFR a zone to us.
- Zone parser error messages were improved slightly (thanks to Stef van Dessel for spotting this shortcoming)
Developers: this version is compatible with the pdns-2.1 development kit, available on <http://downloads.powerdns.com/releases/dev>. See also [Backend writers' guide](appendix/backend-writers-guide.md "Backend writers' guide")
-This release adds the Generic MySQL backend which allows full master/slave semantics with MySQL and InnoDB tables (or other tables that support transactions). See [Generic MySQL and PostgreSQL backends](authoritative/backend-generic-mypgsql.md "Generic MySQL and PostgreSQL backends").
+This release adds the Generic MySQL backend which allows full master/slave semantics with MySQL and InnoDB tables (or other tables that support transactions). See [Generic MySQL backend](authoritative/backend-generic-mysql.md "Generic MySQL backend").
## Other new features
- Improved error messages in master/slave communicator will help down track problems.
- 'Manpage: pdns_server.1': manpages/pdns_server.1.md
- Authoritative Backends:
- BIND: authoritative/backend-bind.md
- - Generic MySQL and PostgreSQL: authoritative/backend-generic-mypgsql.md
- - Generic ODBC: authoritative/backend-godbc.md
+ - Generic SQL Backends: authoritative/backend-generic-sql.md
+ - Generic MySQL: authoritative/backend-generic-mysql.md
+ - Generic ODBC: authoritative/backend-generic-odbc.md
+ - Generic Oracle: authoritative/backend-generic-oracle.md
+ - Generic PostgreSQL: authoritative/backend-generic-postgresql.md
+ - Generic SQLite3: authoritative/backend-generic-sqlite.md
- GeoIP: authoritative/backend-geoip.md
- - Generic SQLite: authoritative/backend-gsqlite.md
- MyDNS: authoritative/backend-mydns.md
- LDAP: authoritative/backend-ldap.md
- Lua: authoritative/backend-lua.md