Выпуск рСляционно-Π³Ρ€Π°Ρ„ΠΎΠ²ΠΎΠΉ Π‘Π£Π‘Π” EdgeDB 4.0

ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»Π΅Π½ Ρ€Π΅Π»ΠΈΠ· Π‘Π£Π‘Π” EdgeDB 4.0, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰Π΅ΠΉ рСляционно-Π³Ρ€Π°Ρ„ΠΎΠ²ΡƒΡŽ модСль Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ язык запросов EdgeQL, ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ со слоТными иСрархичСскими Π΄Π°Π½Π½Ρ‹ΠΌΠΈ. Код написан Π½Π° языках Python ΠΈ Rust (парсСр ΠΈ ΠΊΡ€ΠΈΡ‚ΠΈΡ‡Π½Ρ‹Π΅ ΠΊ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ части) ΠΈ распространяСтся ΠΏΠΎΠ΄ Π»ΠΈΡ†Π΅Π½Π·ΠΈΠ΅ΠΉ Apache 2.0. ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ развиваСтся Π² Ρ„ΠΎΡ€ΠΌΠ΅ надстройки Π½Π°Π΄ PostgreSQL. ΠšΠ»ΠΈΠ΅Π½Ρ‚ΡΠΊΠΈΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²Π»Π΅Π½Ρ‹ для языков Python, Go, Rust. .NET, Elixir ΠΈ TypeScript/Javascript. ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΠ΅Ρ‚ΡΡ инструмСнтарий ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки для управлСния Π‘Π£Π‘Π” ΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ выполнСния запросов (REPL).

ВмСсто ΠΌΠΎΠ΄Π΅Π»ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π° основС Ρ‚Π°Π±Π»ΠΈΡ† Π² EdgeDB примСняСтся дСкларативная систСма Π½Π° основС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ². ВмСсто Π²Π½Π΅ΡˆΠ½ΠΈΡ… ΠΊΠ»ΡŽΡ‡Π΅ΠΉ (foreign key) для опрСдСлСния связи ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ‚ΠΈΠΏΠ°ΠΌΠΈ примСняСтся связываниС ссылками (ΠΎΠ΄ΠΈΠ½ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΊΠ°ΠΊ свойство Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°).

type Person { required name: str; } type Movie { required title: str; multi actors: Person; }

Для ускорСния ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ запросов ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ индСксы. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ‚Π°ΠΊΠΆΠ΅ Ρ‚Π°ΠΊΠΈΠ΅ возмоТности ΠΊΠ°ΠΊ строгая типизация свойств, ограничСния Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ свойств, вычисляСмыС свойства ΠΈ Ρ…Ρ€Π°Π½ΠΈΠΌΡ‹Π΅ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹. Из особСнностСй ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΉ схСмы хранСния EdgeDB, которая Ρ‡Π΅ΠΌ-Ρ‚ΠΎ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ ORM, отмСчаСтся Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ смСшивания схСм, связывания свойств ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ интСгрированная ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° JSON.

ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ встроСнныС инструмСнты для ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ схСмы хранСния — послС измСнСния схСмы, Π·Π°Π΄Π°Π²Π°Π΅ΠΌΠΎΠΉ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ esdl-Ρ„Π°ΠΉΠ»Π΅, достаточно Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ «edgedb migration create» ΠΈ Π‘Π£Π‘Π” ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ различия Π² схСмС ΠΈ Π² ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅ сгСнСрируСт скрипт для ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° Π½Π° Π½ΠΎΠ²ΡƒΡŽ схСму. АвтоматичСски отслСТиваСтся история измСнСния схСмы.

Для формирования запросов поддСрТиваСтся ΠΊΠ°ΠΊ язык запросов GraphQL, Ρ‚Π°ΠΊ ΠΈ собствСнный язык EdgeDB, ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ собой Π°Π΄Π°ΠΏΡ‚Π°Ρ†ΠΈΡŽ SQL для иСрархичСских Π΄Π°Π½Π½Ρ‹Ρ…. ВмСсто списков Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ запроса ΠΎΡ„ΠΎΡ€ΠΌΠ»ΡΡŽΡ‚ΡΡ Π² структурированном Π²ΠΈΠ΄Π΅, Π° вмСсто подзапросов ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ JOIN прСдоставляСтся Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ указания ΠΎΠ΄Π½ΠΎΠ³ΠΎ запроса EdgeQL Π² качСствС выраТСния Π²Π½ΡƒΡ‚Ρ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ запроса. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΈ Ρ†ΠΈΠΊΠ»Ρ‹.

select Movie { title, actors: { name } } filter .title = «The Matrix» insert Movie { title := «The Matrix Resurrections», actors := ( select Person filter .name in { ‘Keanu Reeves’, ‘Carrie-Anne Moss’, ‘Laurence Fishburne’ } ) }

Π’ Π½ΠΎΠ²ΠΎΠΉ вСрсии:

  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° полнотСкстового поиска, рСализованная Ρ‡Π΅Ρ€Π΅Π· ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡ‹ΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ fts. Для прСвращСния любого ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π² доступный для поиска Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ индСкс fts::index, Π° для поиска ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½ΠΎΠΉ Ρ„Ρ€Π°Π·Π΅ срСди проиндСксированных Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½Π° функция fts::search(). Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ΡΡ Π² Ρ„ΠΎΡ€ΠΌΠ΅ ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ΅ΠΉ, содСрТащих Π½Π°ΠΉΠ΄Π΅Π½Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈ Π΅Π³ΠΎ поисковый вСс. НапримСр: type Item { required available: bool { default := false; }; required name: str; required description: str; index fts::index on ( fts::with_options( .name, language := fts::Language.eng ) ); } with res := ( select fts::search(Item, ‘candy corn’, language := ‘eng’) ) select res.object {name, score := res.score} order by res.score desc;
  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½ Π½ΠΎΠ²Ρ‹ΠΉ Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ… «multirange», ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΠΉ ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ нСсколько Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ΠΎΠ² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ для прСдставлСния ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ…ΡΡ ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»ΠΎΠ². Нормализация ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ…ΡΡ областСй Π² Π·Π°Π΄Π°Π½Π½Ρ‹Ρ… Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π°Ρ… осущСствляСтся автоматичСски. Π‘ Ρ‚ΠΈΠΏΠΎΠΌ «multirange» ΠΌΠΎΠ³ΡƒΡ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ всС Ρ€Π°Π½Π΅Π΅ доступныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ΠΎΠ². select multirange([range(8, 10)]) + range(1, 5) — range(3, 4);
  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½Π° ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ для ограничСния доступа ΠΊ GraphQL ΠΈ EdgeQL ΠΏΠΎΠ²Π΅Ρ€Ρ… HTTP.
  • Для запуска сСрвиса Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½ΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ ΠΎΡ‚ экзСмпляра Π‘Π”, Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ «auth», ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‰Π΅Π΅ OAuth ΠΈΠ»ΠΈ Π²Ρ…ΠΎΠ΄ ΠΏΠΎ email ΠΈ ΠΏΠ°Ρ€ΠΎΠ»ΡŽ.
  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ pgcrypto, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰Π΅Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ hmac, gen_salt ΠΈ crypt для Ρ…ΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ΠΈ ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ. select ext::pgcrypto::digest(‘encrypt this’, ‘sha1’);
  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ pg_trgm c функциями для опрСдСлСния схоТСсти строк.
  • ВнСсСны ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ, позволившиС ΠΏΠΎΠ²Ρ‹ΡΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ. ΠŸΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ памяти Π½Π° сСрвСрС сниТСно Π½Π° 40%. Код парсСра запросов EdgeQL пСрСписан Π½Π° языкС Rust.
  • Π’ язык EdgeQL Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ синтаксиса условных Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ (if … then .. else …). ΠŸΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»Π΅Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования условных DML для создания, обновлСния ΠΈ удалСния Ρ€Π°Π·Π½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π½Π° основС Π·Π°Π΄Π°Π½Π½Ρ‹Ρ… условий. Π”ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ to_bytes(), to_str(), enc::base64_encode ΠΈ enc::base64_decode. Π’ Ρ‚Ρ€ΠΈΠ³Π³Π΅Ρ€Π°Ρ… Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ использованиС выраТСния «when». select if count(Object) > 0 then ‘got data’ else ‘no data’; select (select User filter .name = ‘Alice’) ?? (insert User { name := ‘Alice’ }); select enc::base64_encode(b’hello’);
  • Π”ΠΎΠ±Π°Π²Π»Π΅Π½ Π½ΠΎΠ²Ρ‹ΠΉ способ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² запросы GraphQL — вмСсто использования ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ поля прСдоставлСна Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Π½Π° основС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° __globals__.

    Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: opennet.ru