PgGraph рдЕрднрд┐рд▓реЗрдЦ рд░ PostgreSQL рдорд╛ рддрд╛рд▓рд┐рдХрд╛ рдирд┐рд░реНрднрд░рддрд╛рд╣рд░реВ рдлреЗрд▓рд╛ рдкрд╛рд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реЛред

PgGraph рдЕрднрд┐рд▓реЗрдЦ рд░ PostgreSQL рдорд╛ рддрд╛рд▓рд┐рдХрд╛ рдирд┐рд░реНрднрд░рддрд╛рд╣рд░реВ рдлреЗрд▓рд╛ рдкрд╛рд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реЛред
рдЖрдЬ рдо PostgreSQL DBMS рдорд╛ рддрд╛рд▓рд┐рдХрд╛ рдирд┐рд░реНрднрд░рддрд╛ рд╕рдВрдЧ рдХрд╛рдо рдЧрд░реНрди рдХреЛ рд▓рд╛рдЧреА рдкрд╛рдЗрдерди рдорд╛ рд▓реЗрдЦрд┐рдПрдХреЛ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╕рдВрдЧ Habr рдкрд╛рдардХрд╣рд░реБ рдкреНрд░рд╕реНрддреБрдд рдЧрд░реНрди рдЪрд╛рд╣рдиреНрдЫреБред

рдЙрдкрдпреЛрдЧрд┐рддрд╛рдХреЛ API рд╕рд░рд▓ рдЫ рд░ рддреАрди рд╡рд┐рдзрд┐рд╣рд░реВ рд╕рдорд╛рд╡реЗрд╢ рдЫрдиреН:

  • рдЕрднрд┐рд▓реЗрдЦ_рддрд╛рд▓рд┐рдХрд╛ - рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреНрд░рд╛рдердорд┐рдХ рдХреБрдЮреНрдЬреАрд╣рд░реВрдХреЛ рд╕рд╛рде рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╕рдВрдЧреНрд░рд╣ / рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рдореЗрдЯрд╛рдЙрдиреЗ
  • get_table_references - рддрд╛рд▓рд┐рдХрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рд░реНрднрд░рддрд╛рд╣рд░реВ рдЦреЛрдЬреНрдиреБрд╣реЛрд╕реН (рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░рд┐рдПрдХреЛ рд░ рдпрд╕рд▓рд╛рдИ рд╕рдиреНрджрд░реНрдн рдЧрд░реНрдиреЗрд╣рд░реВ рджреНрд╡рд╛рд░рд╛ рд╕рдиреНрджрд░реНрдн рдЧрд░рд┐рдПрдХреЛ рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВ рджреЗрдЦрд╛рдЙрдиреЗрдЫ)
  • get_rows_references - рдЕрдиреНрдп рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВрдорд╛ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рдЦреЛрдЬреНрдиреБрд╣реЛрд╕реН рдЬреБрди рдЗрдЪреНрдЫрд┐рдд рддрд╛рд▓рд┐рдХрд╛рдорд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рд╕рдиреНрджрд░реНрдн рдЧрд░реНрджрдЫ

рдкреНрд░рд╛рдЧрд┐рддрд┐рд╣рд╛рд╕

рдореЗрд░реЛ рдирд╛рдо рдУрд▓реЗрдЧ рдмреЛрд░реНрдЬреЛрдн рд╣реЛ, рдо Domklik рдорд╛ рдзрд┐рддреЛ рдЛрдг рдкреНрд░рдмрдиреНрдзрдХрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ CRM рдЯреЛрд▓реАрдорд╛ рдПрдХ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛ рд╣реБрдБред

рд╣рд╛рдореНрд░реЛ CRM рдкреНрд░рдгрд╛рд▓реАрдХреЛ рдореБрдЦреНрдп рдбрд╛рдЯрд╛рдмреЗрд╕ рдХрдореНрдкрдиреАрдорд╛ рднреЛрд▓реНрдпреБрдордХреЛ рд╣рд┐рд╕рд╛рдмрд▓реЗ рд╕рдмреИрднрдиреНрджрд╛ рдареВрд▓реЛ рдордзреНрдпреЗ рдПрдХ рд╣реЛред рдпреЛ рдкрдирд┐ рд╕рдмреИрднрдиреНрджрд╛ рдкреБрд░рд╛рдиреЛ рдордзреНрдпреЗ рдПрдХ рд╣реЛ: рдпреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯрдХреЛ рдзреЗрд░реИ рд▓рдиреНрдЪрдорд╛ рджреЗрдЦрд╛ рдкрд░реНтАНрдпреЛ, рдЬрдм рд░реВрдЦрд╣рд░реВ рдареВрд▓рд╛ рдерд┐рдП, рдбреЛрдордХреНрд▓рд┐рдХ рдПрдХ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдерд┐рдпреЛ, рд░ рдлреЗрд╕рдирд▓ рдкрд╛рдЗрдерди рдПрд╕рд┐рдиреНрдХреНрд░реЛрдирд╕ рдлреНрд░реЗрдорд╡рд░реНрдХрдорд╛ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрднрд┐рд╕рдХреЛ рд╕рдЯреНрдЯрд╛ PHP рдорд╛ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рдореЛрдиреЛрд▓рд┐рде рдерд┐рдпреЛред

PHP рдмрд╛рдЯ рдкрд╛рдЗрдердирдорд╛ рд╕рдВрдХреНрд░рдордг рдзреЗрд░реИ рд▓рд╛рдореЛ рдерд┐рдпреЛ рд░ рджреБрдмреИ рдкреНрд░рдгрд╛рд▓реАрд╣рд░реВрдХреЛ рдПрдХ рд╕рд╛рде рд╕рдорд░реНрдерди рдЖрд╡рд╢реНрдпрдХ рдерд┐рдпреЛ, рдЬрд╕рд▓реЗ рдбрд╛рдЯрд╛рдмреЗрд╕рдХреЛ рдбрд┐рдЬрд╛рдЗрдирд▓рд╛рдИ рдЕрд╕рд░ рдЧрд░реНтАНрдпреЛред

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

рдбрд╛рдЯрд╛рдмреЗрд╕рдорд╛ рд▓реЛрдб рдХрдо рдЧрд░реНрди, рд╣рд╛рдореАрд▓реЗ рдПрдЙрдЯрд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЗрдЦреНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНрдпреМрдВ рдЬрд╕рд▓реЗ рдкреБрд░рд╛рдиреЛ рд░реЗрдХрд░реНрдбрд╣рд░реВ рд╕рдмреИрднрдиреНрджрд╛ рдареВрд▓реЛ рд░ рд▓реЛрдб рдЧрд░рд┐рдПрдХреЛ рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВрдмрд╛рдЯ рдЕрднрд┐рд▓реЗрдЦрдорд╛ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдЧрд░реНрдиреЗрдЫ (рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдмрд╛рдЯ task ╨▓ task_archive).

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

рдо рдЙрджрд╛рд╣рд░рдг рд╕рд╣рд┐рдд рджреЗрдЦрд╛рдЙрдиреЗрдЫреБ рд╕рд╛рдЗрдЯ postgrespro.ru рдмрд╛рдЯ рдбреЗрдореЛ рдбрд╛рдЯрд╛рдмреЗрд╕:

PgGraph рдЕрднрд┐рд▓реЗрдЦ рд░ PostgreSQL рдорд╛ рддрд╛рд▓рд┐рдХрд╛ рдирд┐рд░реНрднрд░рддрд╛рд╣рд░реВ рдлреЗрд▓рд╛ рдкрд╛рд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реЛред
рдорд╛рдиреМрдВ рд╣рд╛рдореАрд▓реЗ рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рд░реЗрдХрд░реНрдбрд╣рд░реВ рдореЗрдЯрд╛рдЙрди рдЖрд╡рд╢реНрдпрдХ рдЫ Flightsред Postgres рд▓реЗ рд╣рд╛рдореАрд▓рд╛рдИ рдпреЛ рдЬрд╕реНрддреИ рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдБрджреИрди: рд╣рд╛рдореАрд▓реЗ рдкрд╣рд┐рд▓реЗ рд╕рдмреИ рд╕рдиреНрджрд░реНрдн рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВрдмрд╛рдЯ рд░реЗрдХрд░реНрдбрд╣рд░реВ рдореЗрдЯрд╛рдЙрди рдЖрд╡рд╢реНрдпрдХ рдЫ, рд░ рдпрд╕реНрддреИ рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВрдорд╛ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд░реВрдкрдорд╛ рдХрд╕реИрд▓реЗ рдкрдирд┐ рдЙрд▓реНрд▓реЗрдЦ рдЧрд░реНрджреИрдиред

рд╣рд╛рдореНрд░реЛ рдЙрджрд╛рд╣рд░рдг рдорд╛ Flights рдмреБрдЭрд╛рдЙрдБрдЫ Ticket_flightsрд░ рдЙрдирдХреЛ рдорд╛ - Boarding_passes.

рддреНрдпрд╕рдХрд╛рд░рдг, рддрдкрд╛рдИрдВрд▓реЗ рдпрд╕рд▓рд╛рдИ рдпрд╕ рдХреНрд░рдордорд╛ рдореЗрдЯрд╛рдЙрди рдЖрд╡рд╢реНрдпрдХ рдЫ:

  1. рд╣рд╛рдореАрд▓реЗ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВрдХреЛ рдкреНрд░рд╛рдердорд┐рдХ рдХреБрдЮреНрдЬреА (PK) рдорд╛рдирд╣рд░реВ рдкрд╛рдЙрдБрдЫреМрдВ Ticket_flights, рдЬрд╕рд▓реЗ рдореЗрдЯрд┐рдиреЗ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВрд▓рд╛рдИ рд╕рдиреНрджрд░реНрдн рдЧрд░реНрджрдЫ Flights.
  2. рд╣рд╛рдореАрд▓реЗ PK рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рдкрд╛рдЙрдБрдЫреМрдВ 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 тАФ рд▓рдЧрд┐рдЩ рд╕реНрддрд░ (рд╡реИрдХрд▓реНрдкрд┐рдХ рдкреНрдпрд╛рд░рд╛рдорд┐рдЯрд░, рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд INFO рд╣реЛ)ред

рдЖрджреЗрд╢ рдЙрджрд╛рд╣рд░рдгрд╣рд░реВ

рддрд╛рд▓рд┐рдХрд╛ рдЕрднрд┐рд▓реЗрдЦ рдЧрд░реНрджреИ

рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдореБрдЦреНрдп рдкреНрд░рдХрд╛рд░реНрдп рдбрд╛рдЯрд╛ рд╕рдВрдЧреНрд░рд╣ рдЫ, рдЕрд░реНрдерд╛рддреНред рдореБрдЦреНрдп рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдЕрднрд┐рд▓реЗрдЦ рддрд╛рд▓рд┐рдХрд╛рдорд╛ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдЧрд░реНрджреИ (рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдкреБрд╕реНрддрдХрд╣рд░реБ ╨▓ book_archive).

рдЕрднрд┐рд▓реЗрдЦ рдмрд┐рдирд╛ рдореЗрдЯрд╛рдЙрдиреЗ рдкрдирд┐ рд╕рдорд░реНрдерд┐рдд рдЫ: рдпрд╕рдХреЛ рд▓рд╛рдЧрд┐ рддрдкрд╛рдИрдВрд▓реЗ config.ini рдорд╛ рдкреНрдпрд╛рд░рд╛рдорд┐рдЯрд░ рд╕реЗрдЯ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ to_archive = рдЧрд▓рдд).

рдЖрд╡рд╢реНрдпрдХ рдкреНрдпрд╛рд░рд╛рдорд┐рдЯрд░рд╣рд░реВ - config_path, рддрд╛рд▓рд┐рдХрд╛ рд░ рдЖрдИрдбреА.

рд╕реБрд░реБрд╡рд╛рдд рдкрдЫрд┐, рд░реЗрдХрд░реНрдбрд╣рд░реВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдореЗрдЯрд┐рдиреЗ рдЫрдиреН 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 рд▓рд╛рдЗрд╕реЗрдиреНрд╕ рдЕрдиреНрддрд░реНрдЧрдд, рд╕рд╛рдереИ рднрдгреНрдбрд╛рд░рдорд╛ PyPI.

рдо рдЯрд┐рдкреНрдкрдгреА, рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛ рд░ рд╕реБрдЭрд╛рд╡рд╣рд░реВ рдкрд╛рдЙрдБрджрд╛ рдЦреБрд╕реА рд╣реБрдиреЗрдЫреБред

рдо рдпрд╣рд╛рдБ рд░ рднрдгреНрдбрд╛рд░рдорд╛ рдореЗрд░реЛ рдХреНрд╖рдорддрд╛рд▓реЗ рдЙрддреНрддрдо рдкреНрд░рд╢реНрдирд╣рд░реВрдХреЛ рдЬрд╡рд╛рдл рджрд┐рдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрдиреЗрдЫреБред

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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди