예제 #1
0
    def getquoted(self):
        obj = self._wrapped
        if isinstance(obj, six.text_type):
            obj = obj.encode(self.encoding)
        else:
            assert isinstance(obj, six.binary_type)
        string = obj
        length = len(string)

        to_length = (length * 2) + 1
        to = ffi.new('char []', to_length)

        if not self._conn:
            libpq.PQescapeString(to, string, length)
            return b''.join([b"'", ffi.string(to), b"'"])

        if PG_VERSION < 0x090000:
            err = ffi.new('int *')
            libpq.PQescapeStringConn(
                self._conn._pgconn, to, string, length, err)
            if self._conn and self._conn._equote:
                return b''.join([b"E'", ffi.string(to), b"'"])
            return b''.join([b"'", ffi.string(to), b"'"])

        data_pointer = libpq.PQescapeLiteral(
            self._conn._pgconn, string, length)
        data = ffi.string(data_pointer)
        libpq.PQfreemem(data_pointer)
        return data
예제 #2
0
    def _pq_fetch(self):
        pgstatus = libpq.PQresultStatus(self._pgres)
        if pgstatus != libpq.PGRES_FATAL_ERROR:
            self._statusmessage = ffi.string(libpq.PQcmdStatus(self._pgres))
        else:
            self._statusmessage = None

        self._no_tuples = True
        self._rownumber = 0

        if pgstatus == libpq.PGRES_COMMAND_OK:
            rowcount = ffi.string(libpq.PQcmdTuples(self._pgres))
            if not rowcount or not rowcount[0]:
                self._rowcount = -1
            else:
                self._rowcount = int(rowcount)
            self._lastrowid = libpq.PQoidValue(self._pgres)
            self._clear_pgres()

        elif pgstatus == libpq.PGRES_TUPLES_OK:
            self._rowcount = libpq.PQntuples(self._pgres)
            return self._pq_fetch_tuples()

        elif pgstatus == libpq.PGRES_COPY_IN:
            return self._pq_fetch_copy_in()

        elif pgstatus == libpq.PGRES_COPY_OUT:
            return self._pq_fetch_copy_out()

        elif pgstatus == libpq.PGRES_EMPTY_QUERY:
            self._clear_pgres()
            raise ProgrammingError("can't execute an empty query")

        else:
            raise self._conn._create_exception(cursor=self)
예제 #3
0
    def getquoted(self):
        obj = self._wrapped
        if isinstance(self._wrapped, unicode):
            obj = obj.encode(self.encoding)
        string = str(obj)
        length = len(string)

        if not self._conn:
            to = ffi.new('char []', ((length * 2) + 1))
            libpq.PQescapeString(to, string, length)
            return "'%s'" % ffi.string(to)

        if PG_VERSION < 0x090000:
            to = ffi.new('char []', ((length * 2) + 1))
            err = ffi.new('int *')
            libpq.PQescapeStringConn(self._conn._pgconn, to, string, length,
                                     err)

            if self._conn and self._conn._equote:
                return "E'%s'" % ffi.string(to)
            return "'%s'" % ffi.string(to)

        data_pointer = libpq.PQescapeLiteral(self._conn._pgconn, string,
                                             length)
        data = ffi.string(data_pointer)
        libpq.PQfreemem(data_pointer)
        return data
예제 #4
0
    def _pq_fetch(self):
        pgstatus = libpq.PQresultStatus(self._pgres)
        if pgstatus != libpq.PGRES_FATAL_ERROR:
            self._statusmessage = ffi.string(libpq.PQcmdStatus(self._pgres))
        else:
            self._statusmessage = None

        self._no_tuples = True
        self._rownumber = 0

        if pgstatus == libpq.PGRES_COMMAND_OK:
            rowcount = ffi.string(libpq.PQcmdTuples(self._pgres))
            if not rowcount or not rowcount[0]:
                self._rowcount = -1
            else:
                self._rowcount = int(rowcount)
            self._lastrowid = libpq.PQoidValue(self._pgres)
            self._clear_pgres()

        elif pgstatus == libpq.PGRES_TUPLES_OK:
            self._rowcount = libpq.PQntuples(self._pgres)
            return self._pq_fetch_tuples()

        elif pgstatus == libpq.PGRES_COPY_IN:
            return self._pq_fetch_copy_in()

        elif pgstatus == libpq.PGRES_COPY_OUT:
            return self._pq_fetch_copy_out()

        elif pgstatus == libpq.PGRES_EMPTY_QUERY:
            self._clear_pgres()
            raise ProgrammingError("can't execute an empty query")

        else:
            raise self._conn._create_exception(cursor=self)
예제 #5
0
    def getquoted(self):
        obj = self._wrapped
        if isinstance(obj, six.text_type):
            obj = obj.encode(self.encoding)
        else:
            assert isinstance(obj, six.binary_type)
        string = obj
        length = len(string)

        to_length = (length * 2) + 1
        to = ffi.new('char []', to_length)

        if not self._conn:
            libpq.PQescapeString(to, string, length)
            return b''.join([b"'", ffi.string(to), b"'"])

        if PG_VERSION < 0x090000:
            err = ffi.new('int *')
            libpq.PQescapeStringConn(
                self._conn._pgconn, to, string, length, err)
            if self._conn and self._conn._equote:
                return b''.join([b"E'", ffi.string(to), b"'"])
            return b''.join([b"'", ffi.string(to), b"'"])

        data_pointer = libpq.PQescapeLiteral(
            self._conn._pgconn, string, length)
        data = ffi.string(data_pointer)
        libpq.PQfreemem(data_pointer)
        return data
예제 #6
0
    def getquoted(self):
        obj = self._wrapped
        if isinstance(self._wrapped, unicode):
            obj = obj.encode(self.encoding)
        string = str(obj)
        length = len(string)

        if not self._conn:
            to = ffi.new('char []', ((length * 2) + 1))
            libpq.PQescapeString(to, string, length)
            return "'%s'" % ffi.string(to)

        if PG_VERSION < 0x090000:
            to = ffi.new('char []', ((length * 2) + 1))
            err = ffi.new('int *')
            libpq.PQescapeStringConn(
                self._conn._pgconn, to, string, length, err)

            if self._conn and self._conn._equote:
                return "E'%s'" % ffi.string(to)
            return "'%s'" % ffi.string(to)

        data_pointer = libpq.PQescapeLiteral(
            self._conn._pgconn, string, length)
        data = ffi.string(data_pointer)
        libpq.PQfreemem(data_pointer)
        return data
예제 #7
0
    def _create_exception(self, pgres=None, msg=None, cursor=None):
        """Return the appropriate exception instance for the current status.

        IMPORTANT: the new exception takes ownership of pgres: if pgres is
        passed as parameter, the callee must delete its pointer (e.g. it may
        be set to null). If there is a pgres in the cursor it is "stolen": the
        cursor will have it set to Null.

        """
        assert pgres is None or cursor is None, \
            "cannot specify pgres and cursor together"

        if cursor and cursor._pgres:
            pgres, cursor._pgres = cursor._pgres, ffi.NULL

        exc_type = exceptions.OperationalError
        code = pgmsg = None

        # If no custom message is passed then get the message from postgres.
        # If pgres is available then we first try to get the message for the
        # last command, and then the error message for the connection
        if pgres:
            pgmsg = libpq.PQresultErrorMessage(pgres)
            pgmsg = bytes_to_ascii(ffi.string(pgmsg)) if pgmsg else None

            # Get the correct exception class based on the error code
            code = libpq.PQresultErrorField(pgres, libpq.PG_DIAG_SQLSTATE)
            if code != ffi.NULL:
                code = bytes_to_ascii(ffi.string(code))
                exc_type = util.get_exception_for_sqlstate(code)
            else:
                code = None
                exc_type = exceptions.DatabaseError

        if not pgmsg:
            pgmsg = libpq.PQerrorMessage(self._pgconn)
            pgmsg = bytes_to_ascii(ffi.string(pgmsg)) if pgmsg else None

        if msg is None and pgmsg:
            msg = pgmsg
            for prefix in ("ERROR:  ", "FATAL:  ", "PANIC:  "):
                if msg.startswith(prefix):
                    msg = msg[len(prefix):]
                    break

        # Clear the connection if the status is CONNECTION_BAD (fatal error)
        if self._pgconn and libpq.PQstatus(
                self._pgconn) == libpq.CONNECTION_BAD:
            self._closed = 2

        exc = exc_type(msg)
        exc.pgcode = code
        exc.pgerror = pgmsg
        exc.cursor = cursor
        exc._pgres = pgres

        return exc
예제 #8
0
    def _process_notifies(self):
        while True:
            pg_notify = libpq.PQnotifies(self._pgconn)
            if not pg_notify:
                break

            notify = Notify(pg_notify.be_pid,
                            ffi.string(pg_notify.relname).decode(self._py_enc),
                            ffi.string(pg_notify.extra).decode(self._py_enc))
            self._notifies.append(notify)

            libpq.PQfreemem(pg_notify)
예제 #9
0
    def _process_notifies(self):
        while True:
            pg_notify = libpq.PQnotifies(self._pgconn)
            if not pg_notify:
                break

            notify = Notify(
                pg_notify.be_pid,
                ffi.string(pg_notify.relname).decode(self._py_enc),
                ffi.string(pg_notify.extra).decode(self._py_enc))
            self._notifies.append(notify)

            libpq.PQfreemem(pg_notify)
예제 #10
0
    def getquoted(self):
        if self._wrapped is None:
            return b'NULL'

        to_length = ffi.new('size_t *')
        _wrapped = self._wrapped
        if isinstance(_wrapped, six.text_type):
            _wrapped = ascii_to_bytes(_wrapped)
        elif isinstance(_wrapped, _bytearray_types):
            _wrapped = six.binary_type(_wrapped)
        elif not six.PY3 and isinstance(_wrapped, buffer):
            _wrapped = bytes(_wrapped)
        _wrapped = ffi.new('unsigned char[]', _wrapped)

        if self._conn:
            data_pointer = libpq.PQescapeByteaConn(
                self._conn._pgconn, _wrapped, len(self._wrapped), to_length)
        else:
            data_pointer = libpq.PQescapeBytea(
                _wrapped, len(self._wrapped), to_length)

        data = ffi.string(data_pointer)[:to_length[0] - 1]
        libpq.PQfreemem(data_pointer)

        if self._conn and self._conn._equote:
            return b''.join([b"E'", data,  b"'::bytea"])

        return b''.join([b"'", data,  b"'::bytea"])
예제 #11
0
    def getquoted(self):
        if self._wrapped is None:
            return b'NULL'

        to_length = ffi.new('size_t *')
        _wrapped = self._wrapped
        if isinstance(_wrapped, six.text_type):
            _wrapped = unicode_to_bytes(_wrapped)
        elif isinstance(_wrapped, _bytearray_types):
            _wrapped = six.binary_type(_wrapped)
        elif not six.PY3 and isinstance(_wrapped, buffer):
            _wrapped = bytes(_wrapped)
        _wrapped = ffi.new('unsigned char[]', _wrapped)

        if self._conn:
            data_pointer = libpq.PQescapeByteaConn(
                self._conn._pgconn, _wrapped, len(self._wrapped), to_length)
        else:
            data_pointer = libpq.PQescapeBytea(
                _wrapped, len(self._wrapped), to_length)

        data = ffi.string(data_pointer)[:to_length[0] - 1]
        libpq.PQfreemem(data_pointer)

        if self._conn and self._conn._equote:
            return b''.join([b"E'", data,  b"'::bytea"])

        return b''.join([b"'", data,  b"'::bytea"])
예제 #12
0
 def _is_busy(self):
     with self._lock:
         if libpq.PQconsumeInput(self._pgconn) == 0:
             raise exceptions.OperationalError(
                 ffi.string(libpq.PQerrorMessage(self._pgconn)))
         res = libpq.PQisBusy(self._pgconn)
         self._process_notifies()
         return res
예제 #13
0
 def _is_busy(self):
     with self._lock:
         if libpq.PQconsumeInput(self._pgconn) == 0:
             raise exceptions.OperationalError(
                 ffi.string(libpq.PQerrorMessage(self._pgconn)))
         res = libpq.PQisBusy(self._pgconn)
         self._process_notifies()
         return res
예제 #14
0
    def _pq_fetch_tuples(self):
        with self._conn._lock:
            self._nfields = libpq.PQnfields(self._pgres)
            self._no_tuples = False
            description = []
            casts = []
            fast_parsers = []
            for i in xrange(self._nfields):
                ftype = libpq.PQftype(self._pgres, i)
                fsize = libpq.PQfsize(self._pgres, i)
                fmod = libpq.PQfmod(self._pgres, i)
                if fmod > 0:
                    fmod -= 4   # TODO: sizeof(int)

                if fsize == -1:
                    if ftype == 1700:   # NUMERIC
                        isize = fmod >> 16
                    else:
                        isize = fmod
                else:
                    isize = fsize

                if ftype == 1700:
                    prec = (fmod >> 16) & 0xFFFF
                    scale = fmod & 0xFFFF
                else:
                    prec = scale = None

                casts.append(self._get_cast(ftype))
                description.append(Column(
                    name=ffi.string(libpq.PQfname(self._pgres, i))\
                            .decode(self._conn._py_enc),
                    type_code=ftype,
                    display_size=None,
                    internal_size=isize,
                    precision=prec,
                    scale=scale,
                    null_ok=None,
                ))

                fast_parser = None
                if is_32bits:
                    # disable all fast parsers to avoid portability problems
                    pass
                elif ftype == 21 or ftype == 23:
                    fast_parser = libpq.PQEgetint
                elif ftype == 20:
                    fast_parser = libpq.PQEgetlong
                elif ftype == 700:
                    fast_parser = libpq.PQEgetfloat
                elif ftype == 701:
                    fast_parser = libpq.PQEgetdouble
                fast_parsers.append(fast_parser)


            self._description = tuple(description)
            self._casts = casts
            self._fast_parsers = fast_parsers
예제 #15
0
 def _get_field(self, field):
     from psycopg2cffi._impl.adapters import bytes_to_ascii
     if self._exc and self._exc._pgres:
         b = libpq.PQresultErrorField(self._exc._pgres, field)
         if b:
             b = ffi.string(b)
             if six.PY3: # py2 tests insist on str here
                 b = bytes_to_ascii(b)
             return b
예제 #16
0
 def _get_field(self, field):
     from psycopg2cffi._impl.adapters import bytes_to_ascii
     if self._exc and self._exc._pgres:
         b = libpq.PQresultErrorField(self._exc._pgres, field)
         if b:
             b = ffi.string(b)
             if six.PY3: # py2 tests insist on str here
                 b = bytes_to_ascii(b)
             return b
예제 #17
0
    def __init__(self, dsn, **kwargs):

        self.dsn = dsn
        self.status = consts.STATUS_SETUP
        self._encoding = None
        self._py_enc = None

        self._closed = 0
        self._cancel = ffi.NULL
        self._typecasts = {}
        self._tpc_xid = None
        self._notifies = []
        self._autocommit = False
        self._pgconn = None
        self._equote = False
        self._lock = threading.RLock()
        self.notices = []
        self.cursor_factory = None

        # The number of commits/rollbacks done so far
        self._mark = 0

        if 'async' in kwargs:
            self._async = kwargs.pop('async')
        elif 'async_' in kwargs:
            self._async = kwargs.pop('async_')
        else:
            self._async = False

        items = []
        items.extend([(k, v) for (k, v) in kwargs.items() if v is not None])

        if items:
            raise TypeError("'%s' is an invalid keyword argument" %
                            items[0][0])

        self._async_status = consts.ASYNC_DONE
        self._async_cursor = None

        self_ref = weakref.ref(self)
        self._notice_callback = ffi.callback(
            'void(void *, const char *)',
            lambda arg, message: self_ref()._process_notice(
                arg,
                ffi.string(message).decode(self_ref()._py_enc or 'utf-8',
                                           'replace')))

        if not self._async:
            self._connect_sync()
        else:
            self._connect_async()
예제 #18
0
    def __init__(self, dsn, **kwargs):

        self.dsn = dsn
        self.status = consts.STATUS_SETUP
        self._encoding = None
        self._py_enc = None

        self._closed = 0
        self._cancel = ffi.NULL
        self._typecasts = {}
        self._tpc_xid = None
        self._notifies = []
        self._autocommit = False
        self._pgconn = None
        self._equote = False
        self._lock = threading.RLock()
        self.notices = []
        self.cursor_factory = None

        # The number of commits/rollbacks done so far
        self._mark = 0

        if 'async' in kwargs:
            self._async = kwargs.pop('async')
        elif 'async_' in kwargs:
            self._async = kwargs.pop('async_')
        else:
            self._async = False

        items = []
        items.extend([(k, v) for (k, v) in kwargs.items() if v is not None])

        if items:
            raise TypeError("'%s' is an invalid keyword argument" % items[0][0])

        self._async_status = consts.ASYNC_DONE
        self._async_cursor = None

        self_ref = weakref.ref(self)
        self._notice_callback = ffi.callback(
            'void(void *, const char *)',
            lambda arg, message: self_ref()._process_notice(
                arg,
                ffi.string(message).decode(self_ref()._py_enc or 'utf-8', 'replace')))

        if not self._async:
            self._connect_sync()
        else:
            self._connect_async()
예제 #19
0
    def _get_guc(self, name):
        """Return the value of a configuration parameter."""
        with self._lock:
            query = 'SHOW %s' % name

            if _green_callback:
                pgres = self._execute_green(query)
            else:
                pgres = libpq.PQexec(self._pgconn, query)

            if not pgres or libpq.PQresultStatus(pgres) != libpq.PGRES_TUPLES_OK:
                raise exceptions.OperationalError("can't fetch %s" % name)
            rv = ffi.string(libpq.PQgetvalue(pgres, 0, 0))
            libpq.PQclear(pgres)
            return rv
예제 #20
0
    def _get_guc(self, name):
        """Return the value of a configuration parameter."""
        with self._lock:
            query = 'SHOW %s' % name

            if _green_callback:
                pgres = self._execute_green(query)
            else:
                pgres = libpq.PQexec(self._pgconn, ascii_to_bytes(query))

            if not pgres or libpq.PQresultStatus(pgres) != libpq.PGRES_TUPLES_OK:
                raise exceptions.OperationalError("can't fetch %s" % name)
            rv = bytes_to_ascii(ffi.string(libpq.PQgetvalue(pgres, 0, 0)))
            libpq.PQclear(pgres)
            return rv
예제 #21
0
    def read(self, size=-1):
        """Read at most size bytes or to the end of the large object."""
        if size < 0:
            where = self.tell()
            end = self.seek(0, os.SEEK_END)
            self.seek(where, os.SEEK_SET)
            size = end - where

        binary_mode = self._mode & consts.LOBJECT_BINARY
        if size == 0:
            return b'' if binary_mode else ''

        buf = ffi.new('char []', size)
        length = libpq.lo_read(self._conn._pgconn, self._fd, buf, size)
        if length < 0:
            return

        return ffi.buffer(buf, length)[:] if binary_mode else \
               ffi.string(buf).decode(self._conn._py_enc)
예제 #22
0
    def read(self, size=-1):
        """Read at most size bytes or to the end of the large object."""
        if size < 0:
            where = self.tell()
            end = self.seek(0, os.SEEK_END)
            self.seek(where, os.SEEK_SET)
            size = end - where

        binary_mode = self._mode & consts.LOBJECT_BINARY
        if size == 0:
            return b'' if binary_mode else ''

        buf = ffi.new('char []', size)
        length = libpq.lo_read(self._conn._pgconn, self._fd, buf, size)
        if length < 0:
            return

        return ffi.buffer(buf, length)[:] if binary_mode else \
               ffi.string(buf).decode(self._conn._py_enc)
예제 #23
0
    def getquoted(self):
        if self._wrapped is None:
            return 'NULL'

        to_length = ffi.new('size_t *')
        _wrapped = ffi.new('unsigned char[]', str(self._wrapped))
        if self._conn:
            data_pointer = libpq.PQescapeByteaConn(
                self._conn._pgconn, _wrapped, len(self._wrapped), to_length)
        else:
            data_pointer = libpq.PQescapeBytea(
                _wrapped, len(self._wrapped), to_length)

        data = ffi.string(data_pointer)[:to_length[0] - 1]
        libpq.PQfreemem(data_pointer)

        if self._conn and self._conn._equote:
            return r"E'%s'::bytea" % data

        return r"'%s'::bytea" % data
예제 #24
0
    def _pq_fetch_tuples(self):
        with self._conn._lock:
            self._nfields = libpq.PQnfields(self._pgres)
            self._no_tuples = False
            description = []
            casts = []
            for i in xrange(self._nfields):
                ftype = libpq.PQftype(self._pgres, i)
                fsize = libpq.PQfsize(self._pgres, i)
                fmod = libpq.PQfmod(self._pgres, i)
                if fmod > 0:
                    fmod -= 4   # TODO: sizeof(int)

                if fsize == -1:
                    if ftype == 1700:   # NUMERIC
                        isize = fmod >> 16
                    else:
                        isize = fmod
                else:
                    isize = fsize

                if ftype == 1700:
                    prec = (fmod >> 16) & 0xFFFF
                    scale = fmod & 0xFFFF
                else:
                    prec = scale = None

                casts.append(self._get_cast(ftype))
                description.append(Column(
                    name=ffi.string(libpq.PQfname(self._pgres, i)),
                    type_code=ftype,
                    display_size=None,
                    internal_size=isize,
                    precision=prec,
                    scale=scale,
                    null_ok=None,
                ))

            self._description = tuple(description)
            self._casts = casts
예제 #25
0
    def _pq_fetch_tuples(self):
        with self._conn._lock:
            self._nfields = libpq.PQnfields(self._pgres)
            self._no_tuples = False
            description = []
            casts = []
            for i in xrange(self._nfields):
                ftype = libpq.PQftype(self._pgres, i)
                fsize = libpq.PQfsize(self._pgres, i)
                fmod = libpq.PQfmod(self._pgres, i)
                if fmod > 0:
                    fmod -= 4   # TODO: sizeof(int)

                if fsize == -1:
                    if ftype == 1700:   # NUMERIC
                        isize = fmod >> 16
                    else:
                        isize = fmod
                else:
                    isize = fsize

                if ftype == 1700:
                    prec = (fmod >> 16) & 0xFFFF
                    scale = fmod & 0xFFFF
                else:
                    prec = scale = None

                casts.append(self._get_cast(ftype))
                description.append(Column(
                    name=ffi.string(libpq.PQfname(self._pgres, i)),
                    type_code=ftype,
                    display_size=None,
                    internal_size=isize,
                    precision=prec,
                    scale=scale,
                    null_ok=None,
                ))

            self._description = tuple(description)
            self._casts = casts
예제 #26
0
    def getquoted(self):
        if self._wrapped is None:
            return 'NULL'

        to_length = ffi.new('size_t *')
        _wrapped = ffi.new('unsigned char[]', str(self._wrapped))
        if self._conn:
            data_pointer = libpq.PQescapeByteaConn(self._conn._pgconn,
                                                   _wrapped,
                                                   len(self._wrapped),
                                                   to_length)
        else:
            data_pointer = libpq.PQescapeBytea(_wrapped, len(self._wrapped),
                                               to_length)

        data = ffi.string(data_pointer)[:to_length[0] - 1]
        libpq.PQfreemem(data_pointer)

        if self._conn and self._conn._equote:
            return r"E'%s'::bytea" % data

        return r"'%s'::bytea" % data
예제 #27
0
 def _iso_compatible_datestyle(self):
     ''' Return whether connection DateStyle is ISO-compatible
     '''
     datestyle = libpq.PQparameterStatus(self._pgconn, b'DateStyle')
     return datestyle != ffi.NULL and \
             ffi.string(datestyle).startswith(b'ISO')
예제 #28
0
 def _get_field(self, field):
     if self._exc and self._exc._pgres:
         b = libpq.PQresultErrorField(self._exc._pgres, field)
         if b:
             return ffi.string(b)
예제 #29
0
        self._lock = threading.RLock()
        self.notices = []
        self.cursor_factory = None

        # The number of commits/rollbacks done so far
        self._mark = 0

        self._async = async
        self._async_status = consts.ASYNC_DONE
        self._async_cursor = None

        self_ref = weakref.ref(self)
        self._notice_callback = ffi.callback(
            'void(void *, const char *)',
            lambda arg, message: self_ref()._process_notice(
                arg, ffi.string(message)))

        if not self._async:
            self._connect_sync()
        else:
            self._connect_async()

    def _connect_sync(self):
        self._pgconn = libpq.PQconnectdb(self.dsn)
        if not self._pgconn:
            raise exceptions.OperationalError('PQconnectdb() failed')
        elif libpq.PQstatus(self._pgconn) == libpq.CONNECTION_BAD:
            raise self._create_exception()

        # Register notice processor
        libpq.PQsetNoticeProcessor(
예제 #30
0
 def cancel(self):
     err_length = 256
     errbuf = ffi.new('char[]', err_length)
     if libpq.PQcancel(self._cancel, errbuf, err_length) == 0:
         raise exceptions.OperationalError(ffi.string(errbuf))
예제 #31
0
 def get_parameter_status(self, parameter):
     p = libpq.PQparameterStatus(self._pgconn, ascii_to_bytes(parameter))
     return bytes_to_ascii(ffi.string(p)) if p != ffi.NULL else None
예제 #32
0
 def _iso_compatible_datestyle(self):
     ''' Return whether connection DateStyle is ISO-compatible
     '''
     datestyle = libpq.PQparameterStatus(self._pgconn, b'DateStyle')
     return datestyle != ffi.NULL and \
             ffi.string(datestyle).startswith(b'ISO')
예제 #33
0
 def _get_equote(self):
     ret = libpq.PQparameterStatus(
             self._pgconn, b'standard_conforming_strings')
     return ret and ffi.string(ret) == b'off' or False
예제 #34
0
 def get_parameter_status(self, parameter):
     p = libpq.PQparameterStatus(self._pgconn, parameter)
     return ffi.string(p) if p != ffi.NULL else None
예제 #35
0
    def _create_exception(self, pgres=None, msg=None, cursor=None):
        """Return the appropriate exception instance for the current status.

        IMPORTANT: the new exception takes ownership of pgres: if pgres is
        passed as parameter, the callee must delete its pointer (e.g. it may
        be set to null). If there is a pgres in the cursor it is "stolen": the
        cursor will have it set to Null.

        """
        assert pgres is None or cursor is None, \
            "cannot specify pgres and cursor together"

        if cursor and cursor._pgres:
            pgres, cursor._pgres = cursor._pgres, ffi.NULL

        exc_type = exceptions.OperationalError
        code = pgmsg = None
        # _py_enc can be not initialized yet in case of errors when
        # establishing the connection
        err_enc = self._py_enc or 'utf-8'

        # If no custom message is passed then get the message from postgres.
        # If pgres is available then we first try to get the message for the
        # last command, and then the error message for the connection
        if pgres:
            pgmsg = libpq.PQresultErrorMessage(pgres)
            pgmsg = ffi.string(pgmsg).decode(err_enc, 'replace') \
                    if pgmsg else None

            # Get the correct exception class based on the error code
            code = libpq.PQresultErrorField(pgres, libpq.LIBPQ_DIAG_SQLSTATE)
            if code != ffi.NULL:
                code = bytes_to_ascii(ffi.string(code))
                exc_type = util.get_exception_for_sqlstate(code)
            else:
                code = None
                exc_type = exceptions.DatabaseError

        if not pgmsg:
            pgmsg = libpq.PQerrorMessage(self._pgconn)
            pgmsg = ffi.string(pgmsg).decode(err_enc, 'replace') \
                    if pgmsg else None

        if msg is None and pgmsg:
            msg = pgmsg
            for prefix in ("ERROR:  ", "FATAL:  ", "PANIC:  "):
                if msg.startswith(prefix):
                    msg = msg[len(prefix):]
                    break

        # Clear the connection if the status is CONNECTION_BAD (fatal error)
        if self._pgconn and libpq.PQstatus(self._pgconn) == libpq.CONNECTION_BAD:
            self._closed = 2

        exc = exc_type(msg)
        exc.pgcode = code
        exc.pgerror = pgmsg
        exc.cursor = cursor
        exc._pgres = pgres

        return exc
예제 #36
0
 def _get_equote(self):
     ret = libpq.PQparameterStatus(self._pgconn,
                                   b'standard_conforming_strings')
     return ret and ffi.string(ret) == b'off' or False
예제 #37
0
 def cancel(self):
     err_length = 256
     errbuf = ffi.new('char[]', err_length)
     if libpq.PQcancel(self._cancel, errbuf, err_length) == 0:
         raise exceptions.OperationalError(ffi.string(errbuf))
예제 #38
0
 def get_parameter_status(self, parameter):
     p = libpq.PQparameterStatus(self._pgconn, ascii_to_bytes(parameter))
     return bytes_to_ascii(ffi.string(p)) if p != ffi.NULL else None
예제 #39
0
        self._lock = threading.RLock()
        self.notices = []
        self.cursor_factory = None

        # The number of commits/rollbacks done so far
        self._mark = 0

        self._async = async
        self._async_status = consts.ASYNC_DONE
        self._async_cursor = None

        self_ref = weakref.ref(self)
        self._notice_callback = ffi.callback(
            'void(void *, const char *)',
            lambda arg, message: self_ref()._process_notice(
                arg, bytes_to_ascii(ffi.string(message))))

        if not self._async:
            self._connect_sync()
        else:
            self._connect_async()

    def _connect_sync(self):
        self._pgconn = libpq.PQconnectdb(self.dsn.encode('utf-8'))
        if not self._pgconn:
            raise exceptions.OperationalError('PQconnectdb() failed')
        elif libpq.PQstatus(self._pgconn) == libpq.CONNECTION_BAD:
            raise self._create_exception()

        # Register notice processor
        libpq.PQsetNoticeProcessor(self._pgconn, self._notice_callback,
예제 #40
0
        self.notices = []
        self.cursor_factory = None

        # The number of commits/rollbacks done so far
        self._mark = 0

        self._async = async
        self._async_status = consts.ASYNC_DONE
        self._async_cursor = None

        self_ref = weakref.ref(self)
        self._notice_callback = ffi.callback(
            'void(void *, const char *)',
            lambda arg, message: self_ref()._process_notice(
                arg,
                ffi.string(message).decode(self_ref()._py_enc or 'utf-8',
                                           'replace')))

        if not self._async:
            self._connect_sync()
        else:
            self._connect_async()

    def _connect_sync(self):
        self._pgconn = libpq.PQconnectdb(self.dsn.encode('utf-8'))
        if not self._pgconn:
            raise exceptions.OperationalError('PQconnectdb() failed')
        elif libpq.PQstatus(self._pgconn) == libpq.CONNECTION_BAD:
            raise self._create_exception()

        # Register notice processor
        libpq.PQsetNoticeProcessor(self._pgconn, self._notice_callback,