# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
import time
from twisted.internet import defer

class UnauthorizedError(Exception):
    """
    The given key wasn't acceptable for the requested operation.
    """


def postgres_probably_connect(name, username, host):
    """
    Connect to postgres or die trying.
    """
    import pg8000
    module = pg8000
    if host:
        con = pg8000.connect(host=host, user=username, database=name)
    else:
        con = pg8000.connect(
            username,
            unix_sock='/var/run/postgresql/.s.PGSQL.5432',
            database=name)

    return module, con


def sqlite_connect(path):
    import sqlite3
    return sqlite3, sqlite3.connect(path)


def noNullDict(keyValuePairs):
    """
    Eliminate any None values from C{keyValuePairs}.

    @param keyValuePairs: a list of 2-tuples of (key:str, value:(str or None))

    @return: keyValuePairs as a dictionary with any null value-elements
        replaced with empty strings.
    @rtype: L{dict}
    """
    return dict([(k, v or '') for k, v in keyValuePairs])


class DBStore(object):
    """
    Abstract access to Trac's SQL database.

    @param connection: A Python DB-API database connection.
    """
    def __init__(self, connection):
        module, self.connection = connection
        if module.paramstyle == 'qmark':
            self.pl = '?'
        else:
            self.pl = '%s'

    def q(self, query):
        """
        Replace ? in SQL strings with the db driver's placeholder.
        """
        return query.replace('?', self.pl)

    def fetchTicket(self, ticketNumber):
        """
        Look up a ticket and its concomitant changes and attachments.
        """
        c = self.connection.cursor()
        c.execute(self.q(
                "SELECT id, type, time, changetime, component, priority, owner,"
                " reporter, cc, status, resolution, summary, description, "
                "keywords FROM ticket WHERE id = ?"), [ticketNumber])
        ticketRow = c.fetchone()
        ticketFields = ["id", "type", "time", "changetime", "component", "priority", "owner",
                        "reporter", "cc", "status", "resolution", "summary",
                        "description", "keywords"]

        c.execute(self.q("SELECT time, author, field, oldvalue, newvalue "
                         "FROM ticket_change WHERE ticket = ? ORDER BY time"),
                  [ticketNumber])
        changeFields = ['time', 'author', 'field', 'oldvalue', 'newvalue']
        changesRows = c.fetchall()

        c.execute(self.q(