Skip to main content

ora2pg-gap-report

tests PyPI Python License: MIT

Инструмент для оценки миграции Oracle → PostgreSQL Pro (Standard/Certified) до её начала.

pip install ora2pg-gap-report
ora2pg-gap-report path/to/oracle_schema_dump/
Oracle DDL (PACKAGE BODY / TRIGGER / TABLE / INDEX / ...)
                    │
                    ▼
            ora2pg-gap-report
                    │
                    ▼
   37 подтверждённых типов пробелов миграции ora2pg
   ┌──────────────────────────────────────────────────────┐
   │ HIGH    GAP-006  database_link    — @dblink нет в PG  │
   │ HIGH    GAP-023  oracle_text      — CONTAINS()/...    │
   │ MEDIUM  GAP-025  invisible_index  — теряет скрытие    │
   └──────────────────────────────────────────────────────┘

ora2pg-gap-report — сканирование реального PL/SQL-кода в терминале

Проблема

При миграции с Oracle на Postgres Pro в сегменте Standard/Certified (то есть без лицензии на Postgres Pro Enterprise и без проприетарной утилиты ora2pgpro) единственный доступный автоматический конвертер — открытый ora2pg. По независимым оценкам он закрывает в среднем ~80% задачи перевода PL/SQL → PL/pgSQL. Оставшиеся ~20% (пакеты, автономные транзакции, CONNECT BY, вызовы DBMS_*/UTL_*, составные триггеры) сейчас разбираются вручную и, как правило, обнаруживаются постфактум — когда что-то уже сломалось в проде.

Что делает этот инструмент

Сканирует схему Oracle до миграции и говорит: какие конкретно объекты ora2pg пропустит без предупреждения, недооценит по трудоёмкости или сконвертирует потенциально некорректно — и почему. Не замена ora2pg, а надстройка над ним: список того, что он реально не переносит, проверен эмпирически на открытом PL/SQL-коде (docs/research/step0-show-report-baseline.md), а не взят на веру.

Статический анализ Ищет паттерны в исходном Oracle-коде, не требует установленного ora2pg (кроме connect_by, см. ниже)
Воспроизводимо Каждая находка подтверждена реальным прогоном ora2pg + PostgreSQL, а не по документации
6 форматов вывода terminal, markdown, json, csv, sarif, html — один и тот же набор находок
CI-гейт --fail-on + SARIF для GitHub/GitLab code scanning
Работает офлайн Автономный бандл для закрытых контуров (scripts/build_offline_bundle.py), см. ниже
Baseline --save/--baseline — NEW/RESOLVED/UNCHANGED между прогонами
Проверка после миграции --verify — что из pre-migration находок осталось в сгенерированном коде (не функциональная проверка, см. ниже)

Детекторы

Детектор Что ловит
autonomous_tx PRAGMA AUTONOMOUS_TRANSACTION внутри PACKAGE BODY — ora2pg конвертирует через dblink, но занижает/теряет стоимость в SHOW_REPORT/--estimate_cost
compound_triggers COMPOUND TRIGGER — файловый парсер ora2pg тихо возвращает 0 триггеров, без единой ошибки
dbms_utl_calls Классификатор конкретных вызовов DBMS_*/UTL_* — что из них ora2pg реально конвертирует, а что остаётся как есть
connect_by Линтинг сгенерированного ora2pg WITH RECURSIVE на баг с LEVEL. Включается флагом --check-connect-by и, в отличие от остальных, требует установленный ora2pg
merge_delete_clause MERGE ... WHEN MATCHED THEN UPDATE SET ... DELETE WHERE ... — составная Oracle-конструкция без аналога в MERGE PostgreSQL. Обычный MERGE без DELETE WHERE не ловится — не проблема
bulk_collect Локальные TYPE ... IS TABLE OF, BULK COLLECT INTO, FORALL — практически не конвертируются ora2pg. Самый частый в реальном коде из всех детекторов проекта
database_link table@dblink_name — прямая ссылка на удалённую БД через database link. Копируется как есть, эквивалента нет без ручной настройки postgres_fdw/dblink
model_clause MODEL PARTITION BY ... DIMENSION BY ... MEASURES ... RULES — spreadsheet-вычисления в SQL. Не имеет прямого эквивалента в PostgreSQL вообще
pivot_clause PIVOT/UNPIVOT — поворот строк в столбцы прямо в SQL. Копируется как есть, встроенного эквивалента в PostgreSQL нет
object_type CREATE TYPE ... AS OBJECT/TYPE BODY — объектные типы Oracle. --estimate_cost не имеет для них механизма оценки вообще, не просто занижает
with_function WITH FUNCTION/WITH PROCEDURE — встроенная функция внутри WITH. Парсер ora2pg разваливает структуру исходника, а не просто не конвертирует
flashback_query AS OF TIMESTAMP/AS OF SCN — flashback-запрос. Копируется как есть, эквивалента в PostgreSQL нет вообще
global_temp_table CREATE GLOBAL TEMPORARY TABLE — секция ON COMMIT теряется целиком, а умолчания Oracle и PostgreSQL противоположны (тихая смена поведения, не ошибка)
table_partitioning PARTITION BY RANGE/LIST/HASH — секционирование таблицы отбрасывается целиком, без единого предупреждения
connect_by_nocycle CONNECT BY NOCYCLE/ORDER SIBLINGS BY — в отличие от базового CONNECT BY, разваливает структуру всего окружающего PL/SQL-блока
context_object CREATE CONTEXT — application context (часто основа VPD) не конвертируется вообще, след только в DEBUG-логе
insert_all INSERT ALL/INSERT FIRST — многотабличная вставка. Копируется как есть, PL/pgSQL падает на этапе компиляции тела
json_table JSON_TABLE(...) — не существует в PostgreSQL 16 и старше (в 17 есть, но с другим синтаксисом COLUMNS)
external_table CREATE TABLE ... ORGANIZATION EXTERNAL — секция отбрасывается целиком, таблица становится обычной пустой
sql_macro SQL_MACRO — конвертируется в обычную функцию, падает при вызове тем способом, для которого была написана
invisible_column Столбец INVISIBLE теряет своё скрытие — тихо появляется в SELECT * после конвертации
collection_type CREATE TYPE ... TABLE OF/VARRAY OF — коллекционный тип пропадает без следа, зависимые таблицы падают уже при загрузке DDL
cross_apply CROSS APPLY/OUTER APPLY — синтаксиса APPLY нет в PostgreSQL вообще, ближайший эквивалент — JOIN LATERAL
oracle_text Oracle Text — домен-индекс (INDEXTYPE IS CTXSYS.*) отбрасывается, CONTAINS/CATSEARCH/MATCHES не переносятся
recursive_with Нативная рекурсивная WITH ... AS (...) (не через CONNECT BY) без ключевого слова RECURSIVE, которое требует PostgreSQL
invisible_index Индекс INVISIBLE теряет своё скрытие от оптимизатора — PostgreSQL не имеет аналога
read_only_table CREATE TABLE ... READ ONLY теряет гарантию неизменяемости — INSERT проходит там, где Oracle гарантированно блокирует его
materialized_view_log CREATE MATERIALIZED VIEW LOG не конвертируется вообще, след только в DEBUG-логе
identity_column GENERATED ... AS IDENTITY (...) с опциями — баг двойных скобок в самой подстановке ora2pg, не пропуск конвертации
rowid_type ROWID/UROWID как тип столбца — конвертируется в oid, тип-заменитель несовместим с данными, которые должен хранить
sequence_cycle CREATE SEQUENCE ... CYCLE — секция CYCLE отбрасывается, NEXTVAL падает после исчерпания диапазона вместо циклического перезапуска
default_on_null DEFAULT ON NULL копируется verbatim — синтаксическая ошибка уже при применении CREATE TABLE, а не при первой вставке
public_synonym CREATE [PUBLIC] SYNONYM — теряет схему целевого объекта, при совпадении имён получается самоссылающийся VIEW
virtual_column GENERATED ALWAYS AS (...) VIRTUAL — теряет защиту ORA-54016 от явного присваивания, триггер молча подменяет значение
nested_subprogram Локальная вложенная процедура/функция — "утекает" наружу отдельным объектом, содержащий блок пропадает, тело искажается
conditional_compilation $IF/$ELSIF/$ELSE/$END копируются verbatim — падает при первом вызове, не при CREATE
package_state Пакетная переменная — эмуляция через set_config/current_setting сломана (нет приведения типа, нет missing_ok)
index_organized_table ORGANIZATION INDEX (IOT) отбрасывается — таблица становится обычной кучей с отдельным индексом, теряется архитектура хранения

Плюс ora2pg_wrapper.py — запуск ora2pg по типам объектов на выгруженном DDL с парсингом --estimate_cost, и oracle_connector.py/oracle_export.py — живая выгрузка PACKAGE BODY/TRIGGER прямо из Oracle-схемы через DBMS_METADATA.GET_DDL.

Почему почти всё high

Из 37 зарегистрированных gap'ов (gap_registry.py) 33 — high, 4 — medium (context_object, invisible_index, virtual_column, index_organized_table). Отдельно от них есть 38-й детектор, dbms_utl_calls — классификатор вызовов DBMS_*/UTL_*, не привязанный к конкретному GAP-NNN (у него нет одного воспроизводимого минимального примера — это намеренно широкая категория), тоже medium. low в реестре предусмотрен (--severity low, диапазон часов в effort_estimator.py), но пока не присвоен ни одному детектору — это честно, не потому что критерий не придуман, а потому что ни один из подтверждённых случаев в него не попал. Не распределение ради распределения — так сложилось из реальных находок, и вот по какому принципу:

  • high — либо сгенерированный код реально не компилируется/не выполняется в PostgreSQL (подтверждено прогоном на настоящем PostgreSQL 16 — ERROR: syntax error... и подобные, см. таблицу в docs/research/AUDIT.md), либо конструкция пропадает молча, но потеря архитектурно значима: секционирование, внешняя таблица, materialized view log, гарантия READ ONLY, database link — то, что либо ломает миграцию, либо тихо меняет поведение системы так, что это заметят не сразу, а на проде.
  • medium — не блокирует миграцию и не теряет данные, но реальное расхождение поведения, которое стоит перепроверить: invisible_index (индекс перестаёт быть скрытым от оптимизатора — влияет на план запроса, не на корректность), context_object (прикладная фича, часто основа VPD, но сама миграция от её потери не падает), virtual_column (итоговое значение в столбце корректно — теряется не данные, а ранняя диагностика ошибочного явного присваивания), index_organized_table (ограничения целостности сохраняются — теряется архитектура хранения, а не корректность), и отдельно dbms_utl_calls (намеренно широкий классификатор — реальное влияние конкретного вызова слишком разное, чтобы утверждать high для всех разом не покривив душой).

Методология

Этот проект не пытается найти детектор под каждую специфичную для Oracle конструкцию. ROWNUM, DECODE, NVL, SYSDATE, %TYPE, sequences, стандартная семантика исключений — всё это ora2pg конвертирует корректно, и детекторы под них не нужны, как бы по-ораклиному сложно они ни звучали.

Новый детектор появляется только после того, как гипотеза проверена на практике:

  1. Берётся конкретная Oracle-конструкция.
  2. Собирается минимальный воспроизводимый пример.
  3. Пример прогоняется через настоящий ora2pg.
  4. Сгенерированный PostgreSQL-код проверяется на корректность.
  5. Если ora2pg справился — гипотеза отклоняется, детектора не будет. Если нашёлся реальный, воспроизводимый баг — заводится тест-фикстура и пишется детектор.

Так, например, отсеялась изначальная гипотеза про CREATE PACKAGE — на первый взгляд очевидный кандидат, а на практике ora2pg переносит его без проблем (docs/research/step0-show-report-baseline.md). И так же подтвердились COMPOUND TRIGGER и баг с LEVEL в CONNECT BY — оба воспроизведены на реальном прогоне ora2pg, а не предположены по описанию.

Все подтверждённые находки пронумерованы и собраны в docs/research/GAP_REGISTRY.md — по каждой указано, каким детектором она покрыта и на какой версии ora2pg подтверждена. docs/research/AUDIT.md — сводная проверка доказательной базы по каждому подтверждённому gap'у (research-документ, реальный вывод ora2pg, expected/actual, тесты, включая guard-тесты на ложные срабатывания).

Установка и использование

pip install ora2pg-gap-report   # (или: pip install . из клона репозитория)

Сама детекторная библиотека (detectors/, models.py, report_generator.py) — чистый Python без единой внешней зависимости, её можно импортировать отдельно (например, в своих скриптах) вообще без установки чего-либо ещё. У CLI есть одна обязательная зависимость — rich, только ради приятного терминального вывода; ставится сама через pip install.

Сразу после установки доступна команда:

ora2pg-gap-report path/to/schema_dump.pkb another_file.sql

В интерактивном терминале по умолчанию — цветной отчёт: сводная панель (сколько найдено, разбивка по severity, грубая оценка часов), компактная таблица находок и пояснения под каждым сработавшим детектором. Для скриптов/redirect — --format markdown, --format json, --format csv, --format sarif или --format html (markdown работает и как формат по умолчанию, если stdout не терминал):

ora2pg-gap-report path/to/schema_dump.pkb --format json --output report.json
ora2pg-gap-report path/to/schema_dump.pkb --format markdown > report.md
ora2pg-gap-report path/to/schema_dump.pkb --format csv --output report.csv

# SARIF 2.1.0 — для GitHub code scanning (Security tab) или GitLab SAST.
# Severity сопоставлена с уровнями SARIF: high → error, medium → warning,
# low → note (у SARIF нет отдельного уровня critical, как и у самого
# инструмента).
ora2pg-gap-report path/to/schema_dump.pkb --format sarif --output report.sarif

# Самодостаточная HTML-страница (без внешних CSS/JS/шрифтов — открывается
# офлайн) — показать заказчику/руководству, без установки чего-либо.
ora2pg-gap-report path/to/schema_dump.pkb --format html --output report.html

# Опционально: линтинг сгенерированного ora2pg кода для CONNECT BY.
# Требует установленный ora2pg (см. https://github.com/darold/ora2pg) —
# единственная внешняя (не-Python) зависимость во всём проекте, и только
# для этой конкретной проверки.
ora2pg-gap-report path/to/schema_dump.pkb --check-connect-by

Формат --format json описан формальной JSON Schema — schemas/report.schema.json (а формат baseline-снапшота из --save/--baseline — в schemas/baseline.schema.json), чтобы сторонние инструменты могли надёжно парсить вывод, не угадывая по примерам. Обе схемы проверяются в тестах против реального вывода (tests/test_schemas.py) — не просто написаны и оставлены как есть. --format sarif тем же способом проверяется в tests/test_sarif.py против официальной SARIF 2.1.0 схемы OASIS (заведена в tests/fixtures/, чтобы тесты не зависели от сети).

Файлы с DDL можно передавать как есть — один файл может содержать сразу несколько пакетов/триггеров, детекторы разбирают границы объектов сами. Можно передать и директорию — рекурсивно просканируются все .sql/ .pks/.pkb внутри (например, вся папка с выгрузкой DBMS_METADATA.GET_DDL):

ora2pg-gap-report path/to/schema_dump_dir/

ora2pg-gap-report --version — показать установленную версию.

Документация прямо из CLI

--explain GAP-023 (или просто --explain 23) печатает research-документ конкретного gap'а из реестра — Oracle-конструкцию, реальный вывод ora2pg, наблюдаемую проблему, вердикт, а также версии ora2pg/PostgreSQL, на которых находка подтверждена (сейчас 25.0/16 у всех 37 — единая версия, потому что второй пока не было; gap_registry.py уже готов хранить разные версии для будущих находок) — без сканирования файлов:

ora2pg-gap-report --explain GAP-023

Research-документы (docs/research/) — часть репозитория, но не часть pip-пакета (пакет — только сам ora2pg_gap_report/). Если запущено из установленного через pip install пакета, а не из клона репозитория, --explain вместо текста документа покажет прямую ссылку на него на GitHub.

Язык вывода

По умолчанию вывод на русском — не меняется без явного действия, чтобы существующие скрипты и CI, которые парсят текущий вывод, продолжали работать без изменений. Английский доступен как опция:

  • --lang en — только для этого запуска, ничего не сохраняет;
  • --set-lang — открывает выбор языка ([1] English / [2] Русский) и сохраняет его как язык по умолчанию для всех будущих запусков (~/.config/ora2pg-gap-report/language, либо $XDG_CONFIG_HOME);
  • ORA2PG_GAP_REPORT_LANG=en — для CI, не сохраняется;
  • при первом запуске в интерактивном терминале, если язык нигде не задан, --set-lang-выбор показывается один раз сам и сохраняется.

Порядок приоритета: --lang → переменная окружения → сохранённый выбор → интерактивный выбор (только реальный терминал) → русский по умолчанию.

Переведён весь вывод сканирования: терминальный отчёт, --format markdown/html, объяснения и рекомендации по каждому детектору, сообщения об ошибках. Не переведены: --help (нужно знать язык раньше, чем argparse разберёт --lang из аргументов — отдельная задача, не сделана в этом заходе) и сами research-документы docs/research/ (--explain при --lang en печатает их текст на русском, как и раньше, — переведён только заголовок с версиями).

Отслеживание прогресса миграции (baseline)

Схема обычно правится итеративно — снимок «что не так сейчас», потом доработка, потом повторный прогон. --save сохраняет находки текущего прогона как снапшот; --baseline сравнивает следующий прогон с ним и показывает NEW/RESOLVED/UNCHANGED (в stderr, отдельно от самого отчёта):

ora2pg-gap-report path/to/schema_dump/ --save baseline.json
# ... правите схему, конвертируете часть объектов вручную ...
ora2pg-gap-report path/to/schema_dump/ --baseline baseline.json

Находки сопоставляются между прогонами не по номеру строки (он скачет при любой правке файла), а по отпечатку из детектора, файла, объекта и найденного фрагмента — так что находка узнаётся как «та же» даже если вокруг нее переписали код. --save/--baseline всегда работают по полному набору находок, независимо от --severity/--object (эти флаги влияют только на то, что выводится в отчёте).

CI-гейт

--fail-on high (или medium/low) — завершиться с кодом 1, если среди находок есть хотя бы одна с этим уровнем серьёзности или выше (high выше medium выше low). Так же, как --save/--baseline, оценивается по полному набору находок, а не по тому, что осталось после --severity/--object:

ora2pg-gap-report path/to/schema_dump/ --fail-on high
echo $?   # 1, если нашёлся хотя бы один high

Пример реального вывода на открытом пакете — docs/examples/logger-autonomous_tx-report.md.

Оценка трудозатрат в отчёте — грубая эвристика по severity (диапазон часов, не точечное число). Это ориентир для планирования, а не откалиброванная на реальных миграциях оценка — не стоит выдавать её клиенту как обязательство. Диапазон severity оценивает только первое вхождение каждого детектора — повторные находки того же детектора (тот же выученный фикс, применённый ещё раз, не новая задача) считаются по отдельному, гораздо меньшему диапазону, а не как независимые high/medium-задачи каждая: 8 находок autonomous_tx в одном пакете — не 8 отдельных проблем.

Проверка после миграции (--verify)

--save/--baseline сравнивают два прогона по Oracle-исходнику во времени. --verify — другое: сравнивает pre-migration находки с тем, что реально осталось в сгенерированном ora2pg PostgreSQL-коде:

ora2pg-gap-report oracle_schema/ --save migration.json   # до миграции
# ... прогоняете ora2pg, получаете generated_postgresql/ ...
ora2pg-gap-report --verify --baseline migration.json generated_postgresql/
Детекторов в baseline  4
Осталось               2
Не обнаружено          1
Нельзя проверить       1

cross_apply       GAP-022   3 → 1   STILL_PRESENT
json_table        GAP-017   2 → 0   NOT_DETECTED
identity_column   GAP-028   4 → 4   STILL_PRESENT
read_only_table   GAP-026   1 → —   NOT_VERIFIABLE

Это не функциональная проверка — инструмент никуда не подключается, ничего не выполняет, не сравнивает данные. Он статически ищет тот же паттерн уже в сгенерированном коде. И даже так работает не для всех детекторов:

  • Часть конструкций ora2pg копирует в вывод как есть (cross_apply, json_table, identity_column и ещё 10 — полный список в docs/ARCHITECTURE.md) — для них повторный прогон детектора по выводу осмыслен: STILL_PRESENT, если паттерн остался, NOT_DETECTED, если пропал.
  • Часть ora2pg молча выбрасывает (read_only_table, table_partitioning, ещё 13) — конструкции в выводе нет по определению, независимо от того, починил ли кто-то проблему вручную другим способом. Для них честный статус — NOT_VERIFIABLE, а не фиктивный NOT_DETECTED: считать отсутствие доказательством исправления было бы ровно той придуманной уверенностью, которой этот проект специально избегает (см. «Почему почти всё high» выше).

NOT_DETECTED тоже не означает «доказанно исправлено» — только «паттерн не нашёлся в этом коде». Разница мелкая, но именно она отделяет честную проверку от красивой лжи.

--verify — самостоятельный режим: требует --baseline, несовместим с --explain/--save/--fail-on/--check-connect-by/--severity/--object, поддерживает только --format terminal (по умолчанию) и --format json.

Выгрузка DDL прямо из Oracle (опционально)

Если под рукой живая Oracle-схема, а не уже готовый DDL-дамп:

pip install "ora2pg-gap-report[oracle]"   # добавляет python-oracledb, thin-режим, без Instant Client

ora2pg-gap-export --dsn host:1521/ORCLPDB1 --user hr --output-dir dumps/
# пароль — из переменной окружения ORACLE_PASSWORD, либо будет запрошен интерактивно

ora2pg-gap-report dumps/*.sql

ora2pg-gap-export — отдельная команда, не флаг у ora2pg-gap-report, специально: выгрузка требует сетевого доступа к Oracle, анализ — никогда. В закрытом контуре это часто две разные машины (jump host с доступом к БД и изолированная рабочая станция для анализа) — единственное, что должно пересечь границу между ними, это уже выгруженные .sql файлы.

Установка без интернета (закрытый контур)

Целевая аудитория этого инструмента — как раз изолированные сети без выхода наружу, поэтому pip install там обычно не вариант. Решение — собрать самодостаточный архив на машине с интернетом, перенести его любым доступным способом (scp/sftp/через jump host/на флешке) и поставить на целевой машине уже совсем без сети:

# На машине с интернетом, из клона репозитория:
python scripts/build_offline_bundle.py --oracle   # --oracle опционально, --dev для pytest
# → ora2pg-gap-report-offline.tar.gz (пакет + rich + всё транзитивно,
#   включая oracledb и его зависимости, если указан --oracle)

scp ora2pg-gap-report-offline.tar.gz user@jump-host:/tmp/
# ...дальше как получится добраться до целевой машины в контуре —
# sftp, ещё один jump host, физический перенос

# На целевой машине БЕЗ интернета:
tar xzf ora2pg-gap-report-offline.tar.gz
cd ora2pg-gap-report-offline
./install.sh oracle        # или: python3 install.py oracle

install.sh/install.py вызывают pip install --no-index --find-links=./wheels ... — pip ставит целиком из положенных рядом .whl-файлов, ни одного обращения в сеть.

rich и его зависимости (markdown-it-py, pygments, mdurl) — чистый Python, один набор wheel-файлов работает везде. oracledb (только при --oracle) собирает платформозависимые wheel — если машина сборки отличается от целевой по ОС/архитектуре/версии Python, передайте --platform/--python-version/--abi в build_offline_bundle.py (см. --help), чтобы скачать wheel именно под целевую платформу, а не под ту, где запущен скрипт.

Разработка и архитектура

pip install -e ".[dev]"   # editable-режим + pytest
pytest

Как устроен инструмент внутри (лексер, маскирование, атрибуция находок, обработка динамического SQL, файловая структура) — в docs/ARCHITECTURE.md. Как проверять изменения, что за корпус реального открытого кода используется для проверки детекторов, как подтвердить находку на живой Oracle — в docs/DEVELOPMENT.md. Как прислать находку или PR — в CONTRIBUTING.md, нормы поведения — в CODE_OF_CONDUCT.md, как сообщить об уязвимости — в SECURITY.md.

Changelog

История изменений по версиям — CHANGELOG.md.

Лицензия

MIT, см. LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ora2pg_gap_report-0.6.0.tar.gz (226.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ora2pg_gap_report-0.6.0-py3-none-any.whl (177.8 kB view details)

Uploaded Python 3

File details

Details for the file ora2pg_gap_report-0.6.0.tar.gz.

File metadata

  • Download URL: ora2pg_gap_report-0.6.0.tar.gz
  • Upload date:
  • Size: 226.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ora2pg_gap_report-0.6.0.tar.gz
Algorithm Hash digest
SHA256 e19ad7983e9865ee031cf9ec2f0cae9f6f710802063bcf22dc5d15fb8c5c2fd6
MD5 3b2750cb9b9d84245ac8e12cafe74005
BLAKE2b-256 a194206060cecf737648e7d57eba470301d17a9b88585e25fa81b2ce5cb68e5a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ora2pg_gap_report-0.6.0.tar.gz:

Publisher: publish.yml on Lunch418/ora2pg-gap-report

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ora2pg_gap_report-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for ora2pg_gap_report-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 37b35b3dafcf4c92091d7489a49d91ac79c2785c51dc7b97c638614626cb6f95
MD5 576c8898651114a2936018c749ebbee0
BLAKE2b-256 a9f54ea2e01e4adde38b7a391cf509c69a66bd43c2a0c9e6f53a74f173cc7123

See more details on using hashes here.

Provenance

The following attestation bundles were made for ora2pg_gap_report-0.6.0-py3-none-any.whl:

Publisher: publish.yml on Lunch418/ora2pg-gap-report

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page