PgGraph рд╣реА PostgreSQL рдордзреНрдпреЗ рд╕рд╛рд░рдгреА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рдЙрдкрдпреБрдХреНрддрддрд╛ рдЖрд╣реЗ

PgGraph рд╣реА PostgreSQL рдордзреНрдпреЗ рд╕рд╛рд░рдгреА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рдЙрдкрдпреБрдХреНрддрддрд╛ рдЖрд╣реЗ
рдЖрдЬ рдорд▓рд╛ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рдбреАрдмреАрдПрдордПрд╕ рдордзреАрд▓ рдЯреЗрдмрд▓ рдЕрд╡рд▓рдВрдмрдирд╛рдВрд╕рд╣ рдХрд╛рд░реНрдп рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдкрд╛рдпрдердирдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рдЙрдкрдпреБрдХреНрддрддреЗрд╕рд╣ Habr рд╡рд╛рдЪрдХрд╛рдВрдирд╛ рд╕рд╛рджрд░ рдХрд░рд╛рдпрдЪреЗ рдЖрд╣реЗ.

рдпреБрдЯрд┐рд▓рд┐рдЯреАрдЪреЗ API рд╕реЛрдкреЗ рдЖрд╣реЗ рдЖрдгрд┐ рддреНрдпрд╛рдд рддреАрди рдкрджреНрдзрддреАрдВрдЪрд╛ рд╕рдорд╛рд╡реЗрд╢ рдЖрд╣реЗ:

  • рд╕рдВрдЧреНрд░рд╣рдг_рд╕рд╛рд░рдгреА - рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рдердорд┐рдХ рдХреА рд╕рд╣ рд░рд┐рдХрд░реНрд╕рд┐рд╡ рд╕рдВрдЧреНрд░рд╣рдг/рд╣рдЯрд╡рдгреЗ рдкрдВрдХреНрддреА
  • рдорд┐рд│рд╡рд╛_рд╕рд╛рд░рдгреА_рд╕рдВрджрд░реНрдн тАФ рдЯреЗрдмрд▓рд╕рд╛рдареА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╢реЛрдзрд╛ (рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЖрдгрд┐ рддреНрдпрд╛рдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрдгрд╛рд▒реНрдпрд╛ рдЯреЗрдмрд▓реНрд╕ рджрд░реНрд╢рд╡реЗрд▓)
  • рдкрдВрдХреНрддреА_рд╕рдВрджрд░реНрдн рдорд┐рд│рд╡рд╛ - рдЗрдЪреНрдЫрд┐рдд рд╕рд╛рд░рдгреАрдордзреАрд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкрдВрдХреНрддреАрдВрдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрдгрд╛рд▒реНрдпрд╛ рдЗрддрд░ рд╕рд╛рд░рдгреНрдпрд╛рдВрдордзреАрд▓ рдкрдВрдХреНрддреА рд╢реЛрдзрд╛

prehistory

рдорд╛рдЭреЗ рдирд╛рд╡ рдУрд▓реЗрдЧ рдмреЛрд░реНрдЭреЛрд╡реНрд╣ рдЖрд╣реЗ, рдореА рдбреЛрдордХреНрд▓рд┐рдХрдордзреАрд▓ рдЧрд╣рд╛рдг рдХрд░реНрдЬ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХрд╛рдВрдЪреНрдпрд╛ CRM рдЯреАрдордордзреНрдпреЗ рд╡рд┐рдХрд╛рд╕рдХ рдЖрд╣реЗ.

рдЖрдордЪреНрдпрд╛ CRM рд╕рд┐рд╕реНрдЯреАрдордЪрд╛ рдореБрдЦреНрдп рдбреЗрдЯрд╛рдмреЗрд╕ рдХрдВрдкрдиреАрддреАрд▓ рд╡реНрд╣реЙрд▓реНрдпреВрдордЪреНрдпрд╛ рджреГрд╖реНрдЯреАрдиреЗ рд╕рд░реНрд╡рд╛рдд рдореЛрдард╛ рдЖрд╣реЗ. рд╣реЗ рд╕рд░реНрд╡рд╛рдд рдЬреБрдиреЗ рджреЗрдЦреАрд▓ рдЖрд╣реЗ: рддреЗ рдкреНрд░рдХрд▓реНрдкрд╛рдЪреНрдпрд╛ рдЕрдЧрджреА рд▓рд╛рдБрдЪрдЪреНрдпрд╛ рд╡реЗрд│реА рджрд┐рд╕рд▓реЗ, рдЬреЗрд╡реНрд╣рд╛ рдЭрд╛рдбреЗ рдореЛрдареА рд╣реЛрддреА, рдбреЛрдордХреНрд▓рд┐рдХ рдПрдХ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рд╣реЛрддрд╛ рдЖрдгрд┐ рдлреЕрд╢рдиреЗрдмрд▓ рдкрд╛рдпрдерди рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдлреНрд░реЗрдорд╡рд░реНрдХрд╡рд░ рдорд╛рдпрдХреНрд░реЛрд╕рд░реНрд╡реНрд╣рд┐рд╕рдРрд╡рдЬреА PHP рдордзреНрдпреЗ рдПрдХ рдкреНрд░рдЪрдВрдб рдореЛрдиреЛрд▓рд┐рде рд╣реЛрддрд╛.

PHP рддреЗ Python рдордзреАрд▓ рд╕рдВрдХреНрд░рдордг рдЦреВрдк рд▓рд╛рдВрдм рд╣реЛрддреЗ рдЖрдгрд┐ рджреЛрдиреНрд╣реА рдкреНрд░рдгрд╛рд▓реАрдВрдирд╛ рдПрдХрд╛рдЪ рд╡реЗрд│реА рд╕рдорд░реНрдерди рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддреЗ, рдЬреНрдпрд╛рдЪрд╛ рдбреЗрдЯрд╛рдмреЗрд╕рдЪреНрдпрд╛ рдбрд┐рдЭрд╛рдЗрдирд╡рд░ рдкрд░рд┐рдгрд╛рдо рдЭрд╛рд▓рд╛.

рдкрд░рд┐рдгрд╛рдореА, рдЖрдордЪреНрдпрд╛рдХрдбреЗ рд╡рд┐рд╡рд┐рдз рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ рдХреНрд╡реЗрд░реАрдВрд╕рд╛рдареА рдореЛрдареНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдиреЗ рдЬреЛрдбрд▓реЗрд▓реЗ рдЖрдгрд┐ рдкреНрд░рдЪрдВрдб рдЯреЗрдмрд▓реНрд╕ рдЕрд╕рд▓реЗрд▓рд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдЖрд╣реЗ. рд╣реЗ рд╕рд░реНрд╡ рдбреЗрдЯрд╛рдмреЗрд╕рдЪреНрдпрд╛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддреЗрд╡рд░ рдирдХрд╛рд░рд╛рддреНрдордХ рдкрд░рд┐рдгрд╛рдо рдХрд░рддреЗ: рдореЛрдареНрдпрд╛ рд╕рд╛рд░рдгреНрдпрд╛ рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪреНрдпрд╛рддреАрд▓ рдЕрдиреЗрдХ рд╕рдВрдмрдВрдзрд╛рдВрдореБрд│реЗ, рдкреНрд░рд╢реНрдирд╛рдВрдЪреА рдЬрдЯрд┐рд▓рддрд╛ рд╕рддрдд рд╡рд╛рдврдд рдЖрд╣реЗ, рдЬреА рд╕рд░реНрд╡рд╛рдд рдЬрд╛рд╕реНрдд рд▓реЛрдб рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╕рд╛рд░рдгреНрдпрд╛рдВрд╕рд╛рдареА рд╡рд┐рд╢реЗрд╖рддрдГ рдЧрдВрднреАрд░ рдЖрд╣реЗ.

рдбреЗрдЯрд╛рдмреЗрд╕рд╡рд░реАрд▓ рднрд╛рд░ рдХрдореА рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдЖрдореНрд╣реА рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪреЗ рдард░рд╡рд┐рд▓реЗ рдЬреЗ рд╕рд░реНрд╡рд╛рдд рдореЛрдареНрдпрд╛ рдЖрдгрд┐ рд▓реЛрдб рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╕рд╛рд░рдгреНрдпрд╛рдВрдордзреВрди рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХреЗрд▓реЗрд▓реНрдпрд╛рдордзреНрдпреЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдкрд╛рд╕реВрди task ╨▓ task_archive).

рд╣реЗ рдХрд╛рд░реНрдп рдЯреЗрдмрд▓рд╛рдВрдордзреАрд▓ рдореЛрдареНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдиреЗ рд╕рдВрдмрдВрдзрд╛рдВрдореБрд│реЗ рдЧреБрдВрддрд╛рдЧреБрдВрддреАрдЪреЗ рдЖрд╣реЗ: рдлрдХреНрдд рдкрдВрдХреНрддреА рд╣рд▓рд╡рд╛ task ╨▓ task_archive рд╣реЗ рдкреБрд░реЗрд╕реЗ рдирд╛рд╣реА, рддреНрдпрд╛рдЖрдзреА рддреБрдореНрд╣рд╛рд▓рд╛ рддреНрдпрд╛ рд╕рд░реНрд╡ рд╕рдВрджрд░реНрднрд╛рдВрд╕рд╣ рд╡рд╛рд░рдВрд╡рд╛рд░ рддреЗрдЪ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ task рдЯреЗрдмрд▓

рдореА рдЙрджрд╛рд╣рд░рдгрд╛рд╕рд╣ рджрд╛рдЦрд╡реВрди рджреЗрдИрди postgrespro.ru рд╕рд╛рдЗрдЯрд╡рд░реВрди рдбреЗрдореЛ рдбреЗрдЯрд╛рдмреЗрд╕:

PgGraph рд╣реА PostgreSQL рдордзреНрдпреЗ рд╕рд╛рд░рдгреА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдгрд┐ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рдЙрдкрдпреБрдХреНрддрддрд╛ рдЖрд╣реЗ
рд╕рдордЬрд╛ рдЖрдореНрд╣рд╛рд▓рд╛ рдЯреЗрдмрд▓рдордзреВрди рд░реЗрдХреЙрд░реНрдб рд╣рдЯрд╡рдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рдЖрд╣реЗ Flights. Postgres рдЖрдореНрд╣рд╛рд▓рд╛ рдЕрд╕реЗ рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрдгрд╛рд░ рдирд╛рд╣реА: рдЖрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рдердо рд╕рд░реНрд╡ рд╕рдВрджрд░реНрдн рд╕рд╛рд░рдгреНрдпрд╛рдВрдордзреВрди рд░реЗрдХреЙрд░реНрдб рд╣рдЯрд╡рд╛рд╡реЗ рд▓рд╛рдЧрддреАрд▓, рдЖрдгрд┐ рдЕрд╕реЗрдЪ рдХреЛрдгрд╛рд╣реАрджреНрд╡рд╛рд░реЗ рд╕рдВрджрд░реНрднрд┐рдд рдирд╕рд▓реЗрд▓реНрдпрд╛ рд╕рд╛рд░рдгреНрдпрд╛рдВрд╡рд░ рд╡рд╛рд░рдВрд╡рд╛рд░ рдЦрд╛рд▓реА рдЬрд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓.

рдпреЗрдереЗ рдЖрдордЪреНрдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рдд Flights рд╕рдВрджрд░реНрдн рджреЗрддреЗ Ticket_flights, рдЖрдгрд┐ рддрд┐рдЪреНрдпрд╛рд╡рд░ - Boarding_passes.

рдореНрд╣рдгреВрди, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдпрд╛ рдХреНрд░рдорд╛рдиреЗ рддреЗ рд╣рдЯрд╡рд┐рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

  1. рдЖрдореНрд╣рд╛рд▓рд╛ рдкрдВрдХреНрддреАрдВрдЪреА рдкреНрд░рд╛рдердорд┐рдХ рдХреА (рдкреАрдХреЗ) рдореВрд▓реНрдпреЗ рдорд┐рд│рддрд╛рдд Ticket_flights, рдЬреНрдпрд╛рдордзреНрдпреЗ рд╣рдЯрд╡рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдкрдВрдХреНрддреАрдВрдЪрд╛ рд╕рдВрджрд░реНрдн рдЖрд╣реЗ Flights.
  2. рдЖрдореНрд╣рд╛рд▓рд╛ рдкреАрдХреЗ рдкрдВрдХреНрддреА рдорд┐рд│рддрд╛рдд Boarding_passes, рдЬреЗ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛рдд Ticket_flights.
  3. рдЖрдореНрд╣реА рдЯреЗрдмрд▓рдордзреАрд▓ рдЪрд░рдг 2 рд╡рд░реВрди PK рджреНрд╡рд╛рд░реЗ рдкрдВрдХреНрддреА рд╣рдЯрд╡рддреЛ Boarding_passes.
  4. рдЪрд░рдг 1 рдордзреНрдпреЗ PK рджреНрд╡рд╛рд░реЗ рдУрд│реА рд╣рдЯрд╡рд╛ Ticket_flights.
  5. рдкрд╛рд╕реВрди рдУрд│реА рдХрд╛рдвреВрди рдЯрд╛рдХрдд рдЖрд╣реЗ Flights.

рдкрд░рд┐рдгрд╛рдо рдореНрд╣рдгрдЬреЗ PgGraph рдирд╛рд╡рд╛рдЪреА рдпреБрдЯрд┐рд▓рд┐рдЯреА, рдЬреА рдЖрдореНрд╣реА рдУрдкрди рд╕реЛрд░реНрд╕ рдмрдирд╡рдгреНрдпрд╛рдЪрд╛ рдирд┐рд░реНрдгрдп рдШреЗрддрд▓рд╛.

рдХрд╕реЗ рд╡рд╛рдкрд░рд╛рд╡реЗ

рдпреБрдЯрд┐рд▓рд┐рдЯреА рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рджреЛрди рдкрджреНрдзрддреАрдВрдирд╛ рд╕рдорд░реНрдерди рджреЗрддреЗ:

  • рдХрдорд╛рдВрдб рд▓рд╛рдЗрдирд╡рд░реВрди рдХреЙрд▓ рдХрд░рд╛ (pggraph тАж).
  • рдкрд╛рдпрдерди рдХреЛрдбрдордзреНрдпреЗ рд╡рд╛рдкрд░ (рд╡рд░реНрдЧ PgGraphApi).

рд╕реНрдерд╛рдкрдирд╛ рдЖрдгрд┐ рд╕рдВрд░рдЪрдирд╛

рдкреНрд░рдердо рддреБрдореНрд╣рд╛рд▓рд╛ Pypi рд░реЗрдкреЙрдЬрд┐рдЯрд░реАрдордзреВрди рдЙрдкрдпреБрдХреНрддрддрд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЖрд╣реЗ:

pip3 install pggraph

рдирдВрддрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЖрдгрд┐ рд╕рдВрдЧреНрд░рд╣рдг рд╕реНрдХреНрд░рд┐рдкреНрдЯрд╕рд╣ рд╕реНрдерд╛рдирд┐рдХ рдорд╢реАрдирд╡рд░ config.ini рдлрд╛рдЗрд▓ рддрдпрд╛рд░ рдХрд░рд╛:

[db]
host = localhost
port = 5432
user = postgres
password = postgres
dbname = postgres
schema = public ; ╨Э╨╡╨╛╨▒╤П╨╖╨░╤В╨╡╨╗╤М╨╜╤Л╨╣ ╨┐╨░╤А╨░╨╝╨╡╤В╤А, ╤Г╨║╨░╨╖╨░╨╜╨╛ ╨╖╨╜╨░╤З╨╡╨╜╨╕╨╡ ╨┐╨╛ ╤Г╨╝╨╛╨╗╤З╨░╨╜╨╕╤О

[archive]  ; ╨Ф╨░╨╜╨╜╤Л╨╣ ╤А╨░╨╖╨┤╨╡╨╗ ╨╖╨░╨┐╨╛╨╗╨╜╤П╤В╤М ╨╜╨╡╨╛╨▒╤П╨╖╨░╤В╨╡╨╗╤М╨╜╨╛, ╨╜╨╕╨╢╨╡ ╤Г╨║╨░╨╖╨░╨╜╤Л ╨╖╨╜╨░╤З╨╡╨╜╨╕╤П ╨┐╨╛ ╤Г╨╝╨╛╨╗╤З╨░╨╜╨╕╤О
is_debug = false
chunk_size = 1000
max_depth = 20
to_archive = true
archive_suffix = 'archive'

рдХрдиреНрд╕реЛрд▓рд╡рд░реВрди рдЪрд╛рд▓рд╡рд╛

рдорд╛рдкрджрдВрдб

$ pggraph -h
usage: pggraph action [-h] --table TABLE [--ids IDS] [--config_path CONFIG_PATH]
positional arguments:
  action        required action: archive_table, get_table_references, get_rows_references

optional arguments:
  -h, --help                    show this help message and exit
  --table TABLE                 table name
  --ids IDS                     primary key ids, separated by comma, e.g. 1,2,3
  --config_path CONFIG_PATH     path to config.ini
  --log_path LOG_PATH           path to log dir
  --log_level LOG_LEVEL         log level (debug, info, error)

рд╕реНрдерд┐рддреАрд╡рд╛рджреА рдпреБрдХреНрддрд┐рд╡рд╛рдж:

  • action - рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░рд╡рд╛рдИ: archive_table, get_table_references рдХрд┐рдВрд╡рд╛ get_rows_references.

рдирд╛рдорд╛рдВрдХрд┐рдд рдпреБрдХреНрддрд┐рд╡рд╛рдж:

  • --config_path тАФ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдлрд╛рдЗрд▓рдЪрд╛ рдорд╛рд░реНрдЧ;
  • --table - рдПрдХ рд╕рд╛рд░рдгреА рдЬреНрдпрд╛рд╕рд╣ рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ;
  • --ids тАФ рд╕реНрд╡рд▓реНрдкрд╡рд┐рд░рд╛рдорд╛рдиреЗ рд╡рд┐рднрдХреНрдд рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЖрдпрдбреАрдЪреА рдпрд╛рджреА, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, 1,2,3 (рдкрд░реНрдпрд╛рдпреА рдкреЕрд░рд╛рдореАрдЯрд░);
  • --log_path тАФ рд▓реЙрдЧрд╕рд╛рдареА рдлреЛрд▓реНрдбрд░рдЪрд╛ рдорд╛рд░реНрдЧ (рдкрд░реНрдпрд╛рдпреА рдкреЕрд░рд╛рдореАрдЯрд░, рдбреАрдлреЙрд▓реНрдЯрдиреБрд╕рд╛рд░ тАФ рд╣реЛрдо рдлреЛрд▓реНрдбрд░);
  • --log_level тАФ рд▓реЙрдЧрд┐рдВрдЧ рд╕реНрддрд░ (рдкрд░реНрдпрд╛рдпреА рдкреЕрд░рд╛рдореАрдЯрд░, рдбреАрдлреЙрд▓реНрдЯ рдорд╛рд╣рд┐рддреА рдЖрд╣реЗ).

рдЖрдЬреНрдЮрд╛ рдЙрджрд╛рд╣рд░рдгреЗ

рдЯреЗрдмрд▓ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдд рдЖрд╣реЗ

рдпреБрдЯрд┐рд▓рд┐рдЯреАрдЪреЗ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣рдг рдЖрд╣реЗ, рдореНрд╣рдгрдЬреЗ. рдореБрдЦреНрдп рд╕рд╛рд░рдгреАрд╡рд░реВрди рд╕рдВрдЧреНрд░рд╣рдг рд╕рд╛рд░рдгреАрд╡рд░ рдкрдВрдХреНрддреА рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░рдгреЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдЯреЗрдмрд▓рд╡рд░реВрди рдкреБрд╕реНрддрдХреЗ ╨▓ рдкреБрд╕реНрддрдХреЗ_рд╕рдВрдЧреНрд░рд╣).

рд╕рдВрдЧреНрд░рд╣рд┐рдд рди рдХрд░рддрд╛ рд╣рдЯрд╡рдгреЗ рджреЗрдЦреАрд▓ рд╕рдорд░реНрдерд┐рдд рдЖрд╣реЗ: рдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣рд╛рд▓рд╛ config.ini рдордзреНрдпреЗ рдкреЕрд░рд╛рдореАрдЯрд░ рд╕реЗрдЯ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ to_archive = рдЦреЛрдЯреЗ).

рдЖрд╡рд╢реНрдпрдХ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕ - config_path, рдЯреЗрдмрд▓ рдЖрдгрд┐ ids.

рд▓рд╛рдБрдЪ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рд░реЗрдХреЙрд░реНрдб рд╡рд╛рд░рдВрд╡рд╛рд░ рд╣рдЯрд╡рд▓реЗ рдЬрд╛рддреАрд▓ ids рдЯреЗрдмрд▓ рдордзреНрдпреЗ table рдЖрдгрд┐ рддреНрдпрд╛рдЪрд╛ рд╕рдВрджрд░реНрдн рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рд╕рд░реНрд╡ рд╕рд╛рд░рдгреНрдпрд╛рдВрдордзреНрдпреЗ.

$ pggraph archive_table --config_path config.hw.local.ini --table flights --ids 1,2,3
2020-06-20 19:27:44 INFO: flights - START
2020-06-20 19:27:44 INFO: flights - start archive_recursive 3 rows (depth=0)
2020-06-20 19:27:44 INFO:       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:       ticket_flights - start archive_recursive 3 rows (depth=1)
2020-06-20 19:27:44 INFO:               START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               boarding_passes - start archive_recursive 3 rows (depth=2)
2020-06-20 19:27:44 INFO:                       START ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:                       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:               boarding_passes - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:               END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO:       ticket_flights - archive_by_ids 3 rows by ticket_no, flight_id
2020-06-20 19:27:44 INFO:       END ARCHIVE REFERRING TABLES
2020-06-20 19:27:44 INFO: flights - archive_by_ids 3 rows by id
2020-06-20 19:27:44 INFO: flights - END

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рд╛рд░рдгреАрд╕рд╛рдареА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╢реЛрдзрд╛

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рд╛рд░рдгреАрдЪреЗ рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╢реЛрдзрдгреНрдпрд╛рдЪреЗ рдХрд╛рд░реНрдп table. рдЖрд╡рд╢реНрдпрдХ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕ - config_path ╨╕ table.

рд▓реЙрдиреНрдЪ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рд╕реНрдХреНрд░реАрдирд╡рд░ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдИрд▓, рдЬреЗрдереЗ:

  • in_refs тАФ рджрд┐рд▓реЗрд▓реНрдпрд╛ рдПрдХрд╛ рд╕рдВрджрд░реНрднрд╛рддреАрд▓ рд╕рд╛рд░рдгреНрдпрд╛рдВрдЪрд╛ рд╢рдмреНрджрдХреЛрд╢, рдЬрд┐рдереЗ рдХреА рд╣реЗ рдЯреЗрдмрд▓рдЪреЗ рдирд╛рд╡ рдЖрд╣реЗ, рдореВрд▓реНрдп рд╡рд┐рджреЗрд╢реА рдХреА рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕рдЪреА рд╕реВрдЪреА рдЖрд╣реЗ (pk_main - рдореБрдЦреНрдп рдЯреЗрдмрд▓рдордзреАрд▓ рдкреНрд░рд╛рдердорд┐рдХ рдХреА, pk_ref - рд╕рдВрджрд░реНрдн рд╕рд╛рд░рдгреАрдордзреАрд▓ рдкреНрд░рд╛рдердорд┐рдХ рдХреА, fk_ref - рд╕реНрддрдВрднрд╛рдЪреЗ рдирд╛рд╡ рдЬреЗ рд╕реНрддреНрд░реЛрдд рд╕рд╛рд░рдгреАрдЪреА рдкрд░рджреЗрд╢реА рдХреА рдЖрд╣реЗ);
  • out_refs - рдЯреЗрдмрд▓рдЪрд╛ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рдЬреНрдпрд╛рдЪрд╛ рд╕рдВрджрд░реНрдн рдЖрд╣реЗ.

$ pggraph get_table_references --config_path config.hw.local.ini --table flights
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='ticket_no, flight_id', fk_ref='flight_id')]},
 'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
              'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
                           ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рдердорд┐рдХ рдХреА рд╕рд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕рдЪреЗ рд╕рдВрджрд░реНрдн рд╢реЛрдзрдгреЗ

рдлреЙрд░реЗрди рдХреА рджреНрд╡рд╛рд░реЗ рдкрдВрдХреНрддреАрдВрдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрдгрд╛рд▒реНрдпрд╛ рдЗрддрд░ рд╕рд╛рд░рдгреНрдпрд╛рдВрдордзреНрдпреЗ рдкрдВрдХреНрддреА рд╢реЛрдзрдгреНрдпрд╛рдЪреЗ рдХрд╛рд░реНрдп ids рдЯреЗрдмрд▓ table. рдЖрд╡рд╢реНрдпрдХ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕ - config_path, table ╨╕ ids.

рд▓реЙрдиреНрдЪ рдХреЗрд▓реНрдпрд╛рдирдВрддрд░, рд╕реНрдХреНрд░реАрдирд╡рд░ рдЦрд╛рд▓реАрд▓ рд░рдЪрдирд╛ рдЕрд╕рд▓реЗрд▓рд╛ рд╢рдмреНрджрдХреЛрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдИрд▓:

{
	pk_id_1: {
		reffering_table_name_1: {
			foreign_key_1: [
				{row_pk_1: value, row_pk_2: value},
				...
			], 
			...
		},
		...
	},
	pk_id_2: {...},
	...
}

рдЙрджрд╛рд╣рд░рдг рдХреЙрд▓:

$ pggraph get_rows_references --config_path config.hw.local.ini --table flights --ids 1,2,3
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
                                       'ticket_no': '0005432816945'},
                                      {'flight_id': 1,
                                       'ticket_no': '0005432816941'}]}},
 2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
                                       'ticket_no': '0005433101832'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005433101864'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005432919715'}]}},
 3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
                                       'ticket_no': '0005432817560'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817568'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817559'}]}}}

рдХреЛрдбрдордзреНрдпреЗ рд╡рд╛рдкрд░

рдХрдиреНрд╕реЛрд▓рдордзреНрдпреЗ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рд▓рд╛рдпрдмреНрд░рд░реА рдкрд╛рдпрдерди рдХреЛрдбрдордзреНрдпреЗ рд╡рд╛рдкрд░рд▓реА рдЬрд╛рдК рд╢рдХрддреЗ. iPython рдкрд░рд╕реНрдкрд░рд╕рдВрд╡рд╛рджреА рд╡рд╛рддрд╛рд╡рд░рдгрд╛рддреАрд▓ рдХреЙрд▓рдЪреА рдЙрджрд╛рд╣рд░рдгреЗ рдЦрд╛рд▓реА рджрд░реНрд╢рд╡рд┐рд▓реА рдЖрд╣реЗрдд.

рдЯреЗрдмрд▓ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рдд рдЖрд╣реЗ

>>> from pg_graph.main import setup_logging
>>> setup_logging(log_level='DEBUG')
>>> from pg_graph.api import PgGraphApi
>>> api = PgGraphApi('config.hw.local.ini')
>>> api.archive_table('flights', [4,5])
2020-06-20 23:12:08 INFO: flights - START
2020-06-20 23:12:08 INFO: flights - start archive_recursive 2 rows (depth=0)
2020-06-20 23:12:08 INFO: 	START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 	ticket_flights - ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')
2020-06-20 23:12:08 DEBUG: 	SQL('SELECT flight_id, ticket_no FROM bookings.ticket_flights WHERE (flight_id) IN (%s, %s)')
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 30 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 30 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 30 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 30 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 30 rows
2020-06-20 23:12:08 INFO: 	ticket_flights - start archive_recursive 3 rows (depth=1)
2020-06-20 23:12:08 INFO: 		START ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 DEBUG: 		boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: 		boarding_passes - archive_by_fk 3 rows by ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 DEBUG: 		SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: 		DELETE FROM boarding_passes by FK flight_id, ticket_no - 3 rows
2020-06-20 23:12:08 INFO: 		END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: 	ticket_flights - archive_by_ids 3 rows by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: 	SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: 	DELETE FROM ticket_flights by flight_id, ticket_no - 3 rows
2020-06-20 23:12:08 DEBUG: 	INSERT INTO ticket_flights_archive - 3 rows
2020-06-20 23:12:08 INFO: 	END ARCHIVE REFERRING TABLES
2020-06-20 23:12:08 INFO: flights - archive_by_ids 2 rows by flight_id
2020-06-20 23:12:09 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.flights_archive (LIKE bookings.flights)')
2020-06-20 23:12:09 DEBUG: DELETE FROM flights by flight_id - 2 rows
2020-06-20 23:12:09 DEBUG: INSERT INTO flights_archive - 2 rows
2020-06-20 23:12:09 INFO: flights - END

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рд╛рд░рдгреАрд╕рд╛рдареА рдЕрд╡рд▓рдВрдмрд┐рддреНрд╡ рд╢реЛрдзрд╛

>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> res = api.get_table_references('flights')
>>> pprint(res)
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')]},
 'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
              'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
                           ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}

рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рдердорд┐рдХ рдХреА рд╕рд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕рдЪреЗ рд╕рдВрджрд░реНрдн рд╢реЛрдзрдгреЗ

>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> rows = api.get_rows_references('flights', [1,2,3])
>>> pprint(rows)
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
                                       'ticket_no': '0005432816945'},
                                      {'flight_id': 1,
                                       'ticket_no': '0005432816941'}]}},
 2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
                                       'ticket_no': '0005433101832'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005433101864'},
                                      {'flight_id': 2,
                                       'ticket_no': '0005432919715'}]}},
 3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
                                       'ticket_no': '0005432817560'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817568'},
                                      {'flight_id': 3,
                                       'ticket_no': '0005432817559'}]}}}

рд▓рд╛рдпрдмреНрд░рд░реА рд╕реНрддреНрд░реЛрдд рдХреЛрдб рдпреЗрдереЗ рдЙрдкрд▓рдмреНрдз рдЖрд╣реЗ GitHub MIT рдкрд░рд╡рд╛рдиреНрдпрд╛ рдЕрдВрддрд░реНрдЧрдд, рддрд╕реЗрдЪ рднрд╛рдВрдбрд╛рд░рд╛рдд рдкреАрдкреАрдЖрдпрдЖрдп.

рдЯрд┐рдкреНрдкрдгреНрдпрд╛, рд╡рдЪрдирдмрджреНрдзрддрд╛ рдЖрдгрд┐ рд╕реВрдЪрдирд╛рдВрдмрджреНрджрд▓ рдорд▓рд╛ рдЖрдирдВрдж рд╣реЛрдИрд▓.

рдореА рдпреЗрдереЗ рдЖрдгрд┐ рднрд╛рдВрдбрд╛рд░рд╛рдд рдорд╛рдЭреНрдпрд╛ рдХреНрд╖рдорддреЗрдиреБрд╕рд╛рд░ рдкреНрд░рд╢реНрдирд╛рдВрдЪреА рдЙрддреНрддрд░реЗ рджреЗрдгреНрдпрд╛рдЪрд╛ рдкреНрд░рдпрддреНрди рдХрд░реЗрди.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛