Example #1
0
    def _transaction_iterator(self, cursor):
        """Iterate over a list of transactions returned from the database.

        Each row begins with (tid, username, description, extension)
        and may have other columns.
        """
        # Iterating the cursor itself in a generator is not safe if
        # the cursor doesn't actually buffer all the rows *anyway*. If
        # we break from the iterating loop before exhausting all the
        # rows, a subsequent query or close operation can lead to
        # things like MySQL Connector/Python raising
        # InternalError(unread results)
        rows = cursor.fetchall()
        for row in rows:
            tid, username, description, ext = row[:4]
            # Although the transaction interface for username and description are
            # defined as strings, this layer works with bytes. PY3.
            if username is None:
                username = b''
            else:
                username = db_binary_to_bytes(username)

            if description is None:
                description = b''
            else:
                description = db_binary_to_bytes(description)
            if ext is None:
                ext = b''
            else:
                ext = db_binary_to_bytes(ext)


            yield (tid, username, description, ext) + tuple(row[4:])
Example #2
0
    def _transaction_iterator(self, cursor):
        """Iterate over a list of transactions returned from the database.

        Each row begins with (tid, username, description, extension)
        and may have other columns.
        """
        for row in cursor:
            tid, username, description, ext = row[:4]
            # Although the transaction interface for username and description are
            # defined as strings, this layer works with bytes. PY3.
            if username is None:
                username = b''
            else:
                username = db_binary_to_bytes(username)

            if description is None:
                description = b''
            else:
                description = db_binary_to_bytes(description)
            if ext is None:
                ext = b''
            else:
                ext = db_binary_to_bytes(ext)

            yield (tid, username, description, ext) + tuple(row[4:])
Example #3
0
    def _transaction_iterator(self, cursor):
        """Iterate over a list of transactions returned from the database.

        Each row begins with (tid, username, description, extension)
        and may have other columns.
        """
        for row in cursor:
            tid, username, description, ext = row[:4]
            # Although the transaction interface for username and description are
            # defined as strings, this layer works with bytes. PY3.
            if username is None:
                username = b''
            else:
                username = db_binary_to_bytes(username)

            if description is None:
                description = b''
            else:
                description = db_binary_to_bytes(description)
            if ext is None:
                ext = b''
            else:
                ext = db_binary_to_bytes(ext)


            yield (tid, username, description, ext) + tuple(row[4:])
Example #4
0
    def postgresql_load_current(self, cursor, oid):
        """Returns the current pickle and integer tid for an object.

        oid is an integer.  Returns (None, None) if object does not exist.
        """
        if self.keep_history:
            stmt = """
            SELECT state, tid
            FROM current_object
                JOIN object_state USING(zoid, tid)
            WHERE zoid = %s
            """
        else:
            stmt = """
            SELECT state, tid
            FROM object_state
            WHERE zoid = %s
            """
        cursor.execute(stmt, (oid,))
        if cursor.rowcount:
            assert cursor.rowcount == 1
            state, tid = cursor.fetchone()
            state = db_binary_to_bytes(state)
            # If it's None, the object's creation has been
            # undone.
            return state, tid
        else:
            return None, None
Example #5
0
    def _add_refs_for_tid(self, cursor, tid, get_references):
        """Fill object_refs with all states for a transaction.

        Returns the number of references added.
        """
        log.debug("pre_pack: transaction %d: computing references ", tid)
        from_count = 0
        stmt = """
            SELECT zoid, state
            FROM object_state
            WHERE tid = %(tid)s
            """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        add_rows = []  # [(from_oid, tid, to_oid)]
        for from_oid, state in fetchmany(cursor):
            state = db_binary_to_bytes(state)
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            if state:
                assert isinstance(state, bytes), type(
                    state)  # PY3: used to be str(state)
                from_count += 1
                try:
                    to_oids = get_references(state)
                except:
                    log.error(
                        "pre_pack: can't unpickle "
                        "object %d in transaction %d; state length = %d" %
                        (from_oid, tid, len(state)))
                    raise
                for to_oid in to_oids:
                    add_rows.append((from_oid, tid, to_oid))

        # A previous pre-pack may have been interrupted.  Delete rows
        # from the interrupted attempt.
        stmt = "DELETE FROM object_ref WHERE tid = %(tid)s"
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        # Add the new references.
        stmt = """
        INSERT INTO object_ref (zoid, tid, to_zoid)
        VALUES (%s, %s, %s)
        """
        self.runner.run_many(cursor, stmt, add_rows)

        # The references have been computed for this transaction.
        stmt = """
        INSERT INTO object_refs_added (tid)
        VALUES (%(tid)s)
        """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        to_count = len(add_rows)
        log.debug(
            "pre_pack: transaction %d: has %d reference(s) "
            "from %d object(s)", tid, to_count, from_count)
        return to_count
Example #6
0
    def _add_refs_for_tid(self, cursor, tid, get_references):
        """Fill object_refs with all states for a transaction.

        Returns the number of references added.
        """
        log.debug("pre_pack: transaction %d: computing references ", tid)
        from_count = 0
        stmt = """
            SELECT zoid, state
            FROM object_state
            WHERE tid = %(tid)s
            """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        add_rows = []  # [(from_oid, tid, to_oid)]
        for from_oid, state in fetchmany(cursor):
            state = db_binary_to_bytes(state)
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            if state:
                assert isinstance(state, bytes), type(state) # PY3: used to be str(state)
                from_count += 1
                try:
                    to_oids = get_references(state)
                except:
                    log.error(
                        "pre_pack: can't unpickle "
                        "object %d in transaction %d; state length = %d" % (
                            from_oid, tid, len(state)))
                    raise
                for to_oid in to_oids:
                    add_rows.append((from_oid, tid, to_oid))

        # A previous pre-pack may have been interrupted.  Delete rows
        # from the interrupted attempt.
        stmt = "DELETE FROM object_ref WHERE tid = %(tid)s"
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        # Add the new references.
        stmt = """
        INSERT INTO object_ref (zoid, tid, to_zoid)
        VALUES (%s, %s, %s)
        """
        self.runner.run_many(cursor, stmt, add_rows)

        # The references have been computed for this transaction.
        stmt = """
        INSERT INTO object_refs_added (tid)
        VALUES (%(tid)s)
        """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})

        to_count = len(add_rows)
        log.debug("pre_pack: transaction %d: has %d reference(s) "
            "from %d object(s)", tid, to_count, from_count)
        return to_count
Example #7
0
    def _add_refs_for_oids(self, cursor, oids, get_references):
        """Fill object_refs with the states for some objects.

        Returns the number of references added.
        """
        # XXX PY3: This could be tricky
        oid_list = ','.join(str(oid) for oid in oids)
        stmt = """
            SELECT zoid, tid, state
            FROM object_state
            WHERE zoid IN (%s)
            """ % oid_list
        self.runner.run_script_stmt(cursor, stmt)

        add_objects = []
        add_refs = []

        for from_oid, tid, state in self._fetchmany(cursor):
            state = db_binary_to_bytes(state)
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            add_objects.append((from_oid, tid))
            if state:
                assert isinstance(state, bytes), type(state)
                # XXX PY3 state = str(state)
                try:
                    to_oids = get_references(state)
                except:
                    log.error(
                        "pre_pack: can't unpickle "
                        "object %d in transaction %d; state length = %d",
                        from_oid, tid, len(state))
                    raise
                for to_oid in to_oids:
                    add_refs.append((from_oid, tid, to_oid))

        if not add_objects:
            return 0

        stmt = "DELETE FROM object_refs_added WHERE zoid IN (%s)" % oid_list
        self.runner.run_script_stmt(cursor, stmt)
        stmt = "DELETE FROM object_ref WHERE zoid IN (%s)" % oid_list
        self.runner.run_script_stmt(cursor, stmt)

        stmt = """
        INSERT INTO object_ref (zoid, tid, to_zoid) VALUES (%s, %s, %s)
        """
        self.runner.run_many(cursor, stmt, add_refs)

        stmt = """
        INSERT INTO object_refs_added (zoid, tid) VALUES (%s, %s)
        """
        self.runner.run_many(cursor, stmt, add_objects)

        return len(add_refs)
Example #8
0
    def _add_refs_for_oids(self, cursor, oids, get_references):
        """Fill object_refs with the states for some objects.

        Returns the number of references added.
        """
        # XXX PY3: This could be tricky
        oid_list = ','.join(str(oid) for oid in oids)
        stmt = """
            SELECT zoid, tid, state
            FROM object_state
            WHERE zoid IN (%s)
            """ % oid_list
        self.runner.run_script_stmt(cursor, stmt)

        add_objects = []
        add_refs = []

        for from_oid, tid, state in self._fetchmany(cursor):
            state = db_binary_to_bytes(state)
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            add_objects.append((from_oid, tid))
            if state:
                assert isinstance(state, bytes), type(state)
                # XXX PY3 state = str(state)
                try:
                    to_oids = get_references(state)
                except:
                    log.error("pre_pack: can't unpickle "
                              "object %d in transaction %d; state length = %d",
                              from_oid, tid, len(state))
                    raise
                for to_oid in to_oids:
                    add_refs.append((from_oid, tid, to_oid))

        if not add_objects:
            return 0

        stmt = "DELETE FROM object_refs_added WHERE zoid IN (%s)" % oid_list
        self.runner.run_script_stmt(cursor, stmt)
        stmt = "DELETE FROM object_ref WHERE zoid IN (%s)" % oid_list
        self.runner.run_script_stmt(cursor, stmt)

        stmt = """
        INSERT INTO object_ref (zoid, tid, to_zoid) VALUES (%s, %s, %s)
        """
        self.runner.run_many(cursor, stmt, add_refs)

        stmt = """
        INSERT INTO object_refs_added (zoid, tid) VALUES (%s, %s)
        """
        self.runner.run_many(cursor, stmt, add_objects)

        return len(add_refs)
Example #9
0
 def _to_native_str(self, value):
     # Almost all drivers return CHAR/VARCHAR as
     # bytes or possibly str. mysql connector/python, though,
     # will return them as unicode on Py2 if not properly configured.
     # If properly configured, it will return them as bytearray.
     # This doesn't seem configurable.
     # sigh.
     value = db_binary_to_bytes(value)
     if not isinstance(value, str):
         return value.decode('ascii')
     return value
Example #10
0
 def _to_native_str(self, value):
     # Almost all drivers return CHAR/VARCHAR as
     # bytes or possibly str. mysql connector/python, though,
     # will return them as unicode on Py2 if not properly configured.
     # If properly configured, it will return them as bytearray.
     # This doesn't seem configurable.
     # sigh.
     value = db_binary_to_bytes(value)
     if not isinstance(value, str):
         return value.decode('ascii')
     return value
Example #11
0
    def load_revision(self, cursor, oid, tid):
        """Returns the pickle for an object on a particular transaction.

        Returns None if no such state exists.
        """
        stmt = self._load_revision_query
        cursor.execute(stmt, (oid, tid))
        row = cursor.fetchone()
        if row:
            (state,) = row
            return db_binary_to_bytes(state)
        return None
Example #12
0
    def postgresql_load_revision(self, cursor, oid, tid):
        """Returns the pickle for an object on a particular transaction.

        Returns None if no such state exists.
        """
        stmt = """
        SELECT state
        FROM object_state
        WHERE zoid = %s
            AND tid = %s
        """
        cursor.execute(stmt, (oid, tid))
        if cursor.rowcount:
            assert cursor.rowcount == 1
            (state,) = cursor.fetchone()
            return db_binary_to_bytes(state)
        return None
Example #13
0
    def load_current(self, cursor, oid):
        """Returns the current pickle and integer tid for an object.

        oid is an integer.  Returns (None, None) if object does not exist.
        """
        stmt = self._load_current_query

        cursor.execute(stmt, (oid,))
        if cursor.rowcount:
            assert cursor.rowcount == 1
            state, tid = cursor.fetchone()
            state = db_binary_to_bytes(state)
            # If it's None, the object's creation has been
            # undone.
            return state, tid
        else:
            return None, None
Example #14
0
    def iter_objects(self, cursor, tid):
        """Iterate over object states in a transaction.

        Yields (oid, prev_tid, state) for each object state.
        """
        stmt = """
            SELECT zoid, state
            FROM object_state
            WHERE tid = %(tid)s
            ORDER BY zoid
            """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})
        for oid, state in cursor:
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            state = db_binary_to_bytes(state)
            yield oid, state
Example #15
0
    def iter_objects(self, cursor, tid):
        """Iterate over object states in a transaction.

        Yields (oid, prev_tid, state) for each object state.
        """
        stmt = """
            SELECT zoid, state
            FROM object_state
            WHERE tid = %(tid)s
            ORDER BY zoid
            """
        self.runner.run_script_stmt(cursor, stmt, {'tid': tid})
        for oid, state in cursor:
            if hasattr(state, 'read'):
                # Oracle
                state = state.read()
            state = db_binary_to_bytes(state)
            yield oid, state
Example #16
0
    def load_current(self, cursor, oid):
        """Returns the current pickle and integer tid for an object.

        oid is an integer.  Returns (None, None) if object does not exist.
        """
        stmt = self._load_current_query

        cursor.execute(stmt, (oid,))
        # Note that we cannot rely on cursor.rowcount being
        # a valid indicator. The DB-API doesn't require it, and
        # some implementations, like MySQL Connector/Python are
        # unbuffered by default and can't provide it.
        row = cursor.fetchone()
        if row:
            state, tid = row
            state = db_binary_to_bytes(state)
            # If it's None, the object's creation has been
            # undone.
            return state, tid

        return None, None
Example #17
0
    def load_before(self, cursor, oid, tid):
        """Returns the pickle and tid of an object before transaction tid.

        Returns (None, None) if no earlier state exists.
        """
        stmt = """
        SELECT state, tid
        FROM object_state
        WHERE zoid = %s
            AND tid < %s
        ORDER BY tid DESC
        LIMIT 1
        """
        cursor.execute(stmt, (oid, tid))
        row = cursor.fetchone()
        if row:
            state, tid = row
            state = db_binary_to_bytes(state)
            # None in state means The object's creation has been undone
            return state, tid

        return None, None