Esempio n. 1
0
    def check_consistency(
        self,
        db_conn: LoggingDatabaseConnection,
        table: str,
        id_column: str,
        positive: bool = True,
    ):
        txn = db_conn.cursor(txn_name="sequence.check_consistency")

        # First we get the current max ID from the table.
        table_sql = "SELECT GREATEST(%(agg)s(%(id)s), 0) FROM %(table)s" % {
            "id": id_column,
            "table": table,
            "agg": "MAX" if positive else "-MIN",
        }

        txn.execute(table_sql)
        row = txn.fetchone()
        if not row:
            # Table is empty, so nothing to do.
            txn.close()
            return

        # Now we fetch the current value from the sequence and compare with the
        # above.
        max_stream_id = row[0]
        txn.execute("SELECT last_value, is_called FROM %(seq)s" %
                    {"seq": self._sequence_name})
        last_value, is_called = txn.fetchone()
        txn.close()

        # If `is_called` is False then `last_value` is actually the value that
        # will be generated next, so we decrement to get the true "last value".
        if not is_called:
            last_value -= 1

        if max_stream_id > last_value:
            logger.warning(
                "Postgres sequence %s is behind table %s: %d < %d",
                self._sequence_name,
                table,
                last_value,
                max_stream_id,
            )
            raise IncorrectDatabaseSetup(
                _INCONSISTENT_SEQUENCE_ERROR % {
                    "seq": self._sequence_name,
                    "table": table,
                    "max_id_sql": table_sql
                })
Esempio n. 2
0
    def check_consistency(
        self,
        db_conn: "LoggingDatabaseConnection",
        table: str,
        id_column: str,
        stream_name: Optional[str] = None,
        positive: bool = True,
    ):
        """See SequenceGenerator.check_consistency for docstring."""

        txn = db_conn.cursor(txn_name="sequence.check_consistency")

        # First we get the current max ID from the table.
        table_sql = "SELECT GREATEST(%(agg)s(%(id)s), 0) FROM %(table)s" % {
            "id": id_column,
            "table": table,
            "agg": "MAX" if positive else "-MIN",
        }

        txn.execute(table_sql)
        row = txn.fetchone()
        if not row:
            # Table is empty, so nothing to do.
            txn.close()
            return

        # Now we fetch the current value from the sequence and compare with the
        # above.
        max_stream_id = row[0]
        txn.execute("SELECT last_value, is_called FROM %(seq)s" %
                    {"seq": self._sequence_name})
        fetch_res = txn.fetchone()
        assert fetch_res is not None
        last_value, is_called = fetch_res

        # If we have an associated stream check the stream_positions table.
        max_in_stream_positions = None
        if stream_name:
            txn.execute(
                "SELECT MAX(stream_id) FROM stream_positions WHERE stream_name = ?",
                (stream_name, ),
            )
            row = txn.fetchone()
            if row:
                max_in_stream_positions = row[0]

        txn.close()

        # If `is_called` is False then `last_value` is actually the value that
        # will be generated next, so we decrement to get the true "last value".
        if not is_called:
            last_value -= 1

        if max_stream_id > last_value:
            logger.warning(
                "Postgres sequence %s is behind table %s: %d < %d",
                self._sequence_name,
                table,
                last_value,
                max_stream_id,
            )
            raise IncorrectDatabaseSetup(
                _INCONSISTENT_SEQUENCE_ERROR % {
                    "seq": self._sequence_name,
                    "table": table,
                    "max_id_sql": table_sql
                })

        # If we have values in the stream positions table then they have to be
        # less than or equal to `last_value`
        if max_in_stream_positions and max_in_stream_positions > last_value:
            raise IncorrectDatabaseSetup(_INCONSISTENT_STREAM_ERROR % {
                "seq": self._sequence_name,
                "stream_name": stream_name
            })