Net-Base Magazyn

01.07.2026

Modernizacja integracji SQL Server w Delphi: stabilniejsza eksploatacja, łatwiejsze utrzymanie, mniejsze ryzyko

Wiele aplikacji Delphi od lat komunikuje się z SQL Server — często stabilnie, ale obciążone technicznym bagażem: przestarzałymi mechanizmami dostępu do danych, trudno utrzymywalnymi ciągami SQL, niejasnymi transakcjami, słabymi domyślnymi ustawieniami zabezpieczeń oraz problemami z wydajnością przy rosnącym obciążeniu. Ten artykuł pokazuje...

01.07.2026

Od tematu magazynowego do praktyki projektowej

Pasujące strony usługowe i techniczne do artykułu

Kto chce zmodernizować podłączenie do SQL Server w Delphi, rzadko ma do czynienia z problemem „da się czy nie da się“. W wielu firmach powstałe przez lata Delphi desktopowe aplikacje lub Windows-usługi działają latami niezawodnie – aż pojawią się nowe wymagania: aktualizacje Windows, nowe wersje SQL Server, zaostrzone wymogi bezpieczeństwa, większe wolumeny danych, więcej lokalizacji lub konieczność czystego kapsułkowania interfejsów. Wtedy staje się widoczne, jak mocno dostęp do danych, obsługa błędów i logika transakcyjna wpływają na codzienną pracę administracji i eksploatację.

Ten artykuł opisuje konkretne kroki modernizacyjne, które można wdrożyć w istniejących systemach bez konieczności budowania wszystkiego od nowa. Fokus leży na decyzjach istotnych dla kierownictwa IT, administratorów i technicznych osób odpowiedzialnych za projekty: wybór sterownika, poziom bezpieczeństwa, stabilność eksploatacji, utrzymywalność, wydajność oraz ścieżka migracji o niskim ryzyku.

Dlaczego podłączenie do SQL Server w Delphi staje się tematem modernizacji

W praktyce presję modernizacyjną rzadko generuje sama język Delphi, a raczej współzależność bazy danych, środowiska sterowników, utwardzania systemu operacyjnego i rosnącej złożoności oprogramowania biznesowego. Typowe wyzwalacze to:

  • Techniczne obciążenia w dostępie do danych: stare ścieżki ADO-/OLE-DB, ręcznie konfigurowane ODBC, niejednolite ustawienia połączeń lub mieszane komponenty w projekcie.
  • Domyślne ustawienia bezpieczeństwa są niewystarczające: wymagania dotyczące szyfrowania TLS (szyfrowanie transportu), weryfikacji certyfikatów, rotacji haseł lub Windows-uwierzytelniania.
  • Bóle wydajnościowe: rosnąca liczba użytkowników, większa równoległość, nowe raporty, dodatkowe integracje – i nagle pojawiają się timeouty, deadlocki lub długotrwałe blokady.
  • Utrzymywalność pogarsza się: SQL-owe zapytania w formularzach, brak parametryzacji, „try/except” bez kontekstu diagnostycznego, niejasne granice transakcji.
  • Skoki platformy i wersji: aktualizacja do nowych wersji SQL Server lub Windows, przejście na 64 bity, Terminal Server/RemoteApp lub wirtualizacja.

Główna konkluzja: zmodernizowane podłączenie to nie tylko „szybsze“. To bardziej opanowalne: przejrzala eksploatacja, odtwarzalna konfiguracja, informacyjne logi oraz dostęp do danych, który można testować i odnawiać krok po kroku.

Dokładne zbadanie stanu obecnego: zanim „po prostu wbuduje się FireDAC“

Zanim wymieniane zostaną komponenty, warto przeprowadzić krótką, uporządkowaną inwentaryzację. Oszczędza to później dni na poszukiwaniu błędów, ponieważ ujawnia zależności, które w starych projektach często istnieją tylko implicitnie.

Lista kontrolna: co musi być wyjaśnione w analizie?

  • Jaką technologię dostępu? ADO (przez OLE DB), ODBC, dbExpress, pozostałości BDE, biblioteki własnościowe – i gdzie są rozproszone w kodzie?
  • Jak budowane są połączenia? Connection string centralnie czy per moduł? Czy są pliki konfiguracyjne, wpisy w rejestrze, zmienne środowiskowe?
  • Jak przebiega uwierzytelnianie? login SQL, Windows Authentication (logowanie zintegrowane), konta serwisowe, Kerberos/NTLM, ewentualnie tryby mieszane.
  • Jak wykorzystywane są transakcje? na operację zapisu, na przypadek użycia, czy wręcz „autocommit” bez jasnych granic?
  • Jakie funkcje SQL Server są używane? procedury składowane, widoki, triggery, CLR, Always On, szyfrowanie, Columnstore, Temporal Tables.
  • Jakie środowiska eksploatacyjne? jednostanowiskowa, Terminalserver, Citrix, Windows- und Linux-Services, zaplanowane zadania, wiele lokalizacji z VPN.
  • Jednym z rezultatów tej fazy powinno być zwięzłe docelowe ujęcie: które moduły zostaną zmodernizowane jako pierwsze, które ustawienia zostaną ustandaryzowane oraz które ryzyka (np. zmiana sposobu uwierzytelniania) zostaną świadomie traktowane oddzielnie.

    Modernizacja połączenia SQL Server w Delphi: strategia sterowników i komponentów

    Dla wielu systemów Delphi kluczowa decyzja to: jak technicznie komunikujemy się z SQL Server — i jak ustandaryzować to we wszystkich modułach? W nowoczesnych stosach Delphi praktycznym standardem bywa BDE-zastąpienie z natywną integracją. BDE-Ablosung mit nativer Anbindung jest warstwą dostępu do danych (Data Access Layer) w Delphi, która kapsułuje sterowniki, wspiera parametryzację i potrafi czytelnie odzwierciedlić typowe wymagania operacyjne, takie jak poolowanie i logowanie.

    Dlaczego standaryzacja jest ważniejsza niż „idealny sterownik”

    W aplikacjach istniejących często występuje tryb mieszany: część korzysta z ADO, inna z ODBC, jeszcze inna z dbExpress. To prowadzi do podwójnej konfiguracji, różnych semantyk timeoutów i transakcji oraz trudnych do porównania symptomów błędów. Celem modernizacji powinno być:

    • jednolity standard połączenia (w tym timeouty, szyfrowanie, nazwa aplikacji),
    • wspólna koncepcja obsługi błędów i logowania,
    • wyraźnie zdefiniowana warstwa abstrakcji między logiką UI/usług a SQL.

    Zastąpić ADO czy je opakować?

    Wiele systemów używa ADO, bo kiedyś „po prostu działało”. Dziś ADO nie jest automatycznie złe, ale często utrudnia jednolite domyślne ustawienia bezpieczeństwa, strategie poolowania i diagnostykę. W praktyce są dwie wykonalne ścieżki:

    • Kapsułkowanie: ADO pozostaje na początek, ale wprowadza się fasadę dostępu do danych, tak aby nowe moduły były już poprawnie podłączone.
    • Stopniowa wymiana: moduły lub przypadki użycia są kolejno przełączane na FireDAC, w towarzystwie testów regresyjnych i pracy w trybie równoległym.

    Która opcja jest właściwa zależy od presji wydania, pokrycia testami i złożoności logiki SQL — w mniejszym stopniu od samej liczby formularzy.

    Bezpieczeństwo w integracji z bazą danych: TLS, tożsamości i prawidłowe zarządzanie uprawnieniami

    Z perspektywy operacyjnej połączenie z bazą danych to kluczowy temat bezpieczeństwa. Chodzi o szyfrowanie transportu, tożsamości, minimalne uprawnienia i konfigurowalność dającą się odtworzyć. Zwłaszcza w aplikacjach rozwijanych przez lata domyślne ustawienia często są historyczne, a nie świadomie dobrane.

    Szyfrowanie transportu (TLS) i weryfikacja certyfikatów

    SQL Server może szyfrować połączenia za pomocą TLS. Ważne jest nie tylko włączenie „Encrypt”, lecz także weryfikacja certyfikatu i spójne zarządzanie certyfikatami (np. poprawne Subject Alternative Names). W przeciwnym razie wpada się w pułapkę: szyfrowanie aktywne, ale dzięki „Trust Server Certificate” w praktyce bez rzeczywistej weryfikacji.

    Dla administratorów istotne jest: konfiguracja musi być odtwarzalna (GPO/Deployment), a komunikaty o błędach powinny być jednoznaczne (np. certyfikat wygasł vs. nieprawidłowa nazwa DNS).

    SQL-Login vs. Windows-uwierzytelnianie

    Loginy SQL są łatwe do dystrybucji, ale trudniejsze w bezpiecznym eksploatowaniu: rotacja haseł, obsługa sekretów i ryzyko nadużyć. Windows Authentication (integrowane logowanie) może przynieść korzyści w środowisku korporacyjnym, lecz wymaga jasnych warunków ramowych: kont usługowych, SPNs (Service Principal Names) i ścieżek Kerberos muszą być poprawnie skonfigurowane, szczególnie przy dostępie przez wielokrotne skoki (np. serwer terminali do bazy danych).

    Praktyczna modernizacja często wygląda następująco: Windows Authentication dla komponentów serwerowych (Windows- und Linux-Services, REST-Server) oraz jasno uregulowane loginy dla przypadków szczególnych – zawsze z minimalnymi uprawnieniami.

    Koncepcja uprawnień: mniej oznacza większą stabilność

    Odporność na awarie zależy również od uprawnień. Zbyt szerokie uprawnienia prowadzą do „skutków ubocznych“: nieoczekiwanych zmian schematu, usunięć danych lub obchodzenia reguł biznesowych. Sprawdzone praktyki to:

    • Role bazy danych dla każdej aplikacji (odczyt, zapis, uprawnienia administracyjne oddzielnie),
    • Jawne uprawnienia zamiast przynależności do potężnych ról domyślnych,
    • Wyraźne rozdzielenie DDL (zmiany schematu) i DML (zmiany danych) przez wdrożenia.

    Wydajność i stabilność: pooling połączeń, timeouty, blokady

    Wiele problemów z wydajnością to nie „SQL Server jest wolny”, lecz konsekwencja niespójnych strategii po stronie klienta: zbyt wiele połączeń, błędne timeouty, akcje interfejsu użytkownika przekraczające granice transakcji lub nieparametryzowane zapytania. Modernizacja oznacza tutaj: uczynić dostęp do danych planowalnym.

    Połączenia: otwieranie/zamykanie vs. pooling

    W aplikacjach desktopowych zwyczajowo otwiera się połączenia na żądanie. W procesach serwerowych (Windows-Service, REST-Server) pooling połączeń jest kluczowy, by przechwycić skoki obciążenia. Pooling oznacza: połączenia są ponownie wykorzystywane zamiast budować nowe dla każdego żądania. To zmniejsza narzut logowania i stabilizuje czasy odpowiedzi.

    Istotna jest strona operacyjna: pooling wymaga jasnych limitów, sensownych timeoutów bezczynności i monitoringu, aby „zawieszone” połączenia stały się widoczne. W przeciwnym razie tylko przesuwamy problemy.

    Timeouty: trzy poziomy, jeden cel

    W scenariuszach z SQL Server timeouty działają na kilku poziomach: sieć/gniazdo, logowanie/handshake oraz timeout polecenia (czas wykonania). Nowoczesne podejście do integracji oznacza: świadome ustawianie tych wartości i uzasadnianie ich dla każdego przypadku użycia (np. wyszukiwanie interaktywne vs. nocny batch).

    W eksploatacji powinno być możliwe stwierdzenie, czy timeout wynika z brakujących indeksów, blokad czy problemów sieciowych. To działa tylko wtedy, gdy aplikacja loguje kontekst (typ zapytania, parametry, czas trwania, nazwa serwera).

    Opanowanie transakcji i blokad (locking)

    Transakcje są kluczowym zagadnieniem stabilności. Transakcja to spójny ciąg zmian danych, które są stosowane albo w całości, albo wcale. W praktyce problemy pojawiają się, gdy transakcje pozostają otwarte zbyt długo — na przykład dlatego, że w ramach transakcji wykonywane są akcje UI, potwierdzenia użytkownika lub dostęp do plików.

    Kroki modernizacyjne przynoszące natychmiastowy efekt:

    • Definiować granice transakcji dla operacji merytorycznych (np. „zarejestrowanie zlecenia”), nie dla formularza.
    • Brak interaktywnych oczekiwań wewnątrz transakcji (dialogi, długie obliczenia, druk/PDF).
  • Umożliwić analizę deadlocków: Rozszerzyć obsługę błędów tak, aby ofiary deadlocków były rozpoznawalne i aby można było celowo stosować strategie ponawiania.
  • Zwiększyć utrzymywalność: enkapsulacja SQL, wymuszanie parametryzacji, poprawa diagnostyki błędów

    Wiele projektów istniejących Delphi cierpi mniej z powodu „zbyt małej liczby funkcji”, a bardziej z powodu niejasnego dostępu do danych. Utrzymywalność powstaje, gdy SQL i logika danych nie są rozproszone po całym kodzie, lecz osadzone w kilku możliwych do prześledzenia miejscach.

    Ciągi SQL w interfejsie użytkownika to ryzyko utrzymania

    Jeśli każdy formularz sam buduje własne ciągi SQL, każda zmiana schematu staje się kosztowna. Dodatkowo rosną ryzyka bezpieczeństwa (np. SQL Injection) i diagnoza staje się trudna. Nowoczesne podejście to warstwa dostępu do danych, która:

    • centralnie zarządza instrukcjami SQL (na moduł/przypadek użycia),
    • konsekwentnie stosuje parametryzację (zamiast konkatenacji ciągów),
    • zwraca dane w czytelnych strukturach (zamiast „Dataset” wszędzie).

    Dla zespołów bez dużych zasobów deweloperskich cenny jest już krok pośredni: ujednolicona fabryka zapytań i stałe reguły dotyczące tego, gdzie może leżeć SQL.

    Stored Procedures vs. Inline SQL: realia operacyjne zamiast kwestii wiary

    Stored Procedures (procedury składowane w SQL Server) mogą przynieść korzyści: centralna logika, koncepcje uprawnień i często bardziej stabilne plany wykonania. Inline SQL jest za to szybszy do zmiany i dla wielu zespołów lepiej wersjonowalny w tym samym procesie wydawniczym co aplikacja.

    W praktyce powszechna jest strategia mieszana:

    • Krytyczne operacje zapisu (księgowania, ruchy magazynowe) raczej proceduralne, gdy priorytetem są uprawnienia i spójność.
    • Zapytania obciążone odczytem (wyszukiwania, listy, raporty) raczej jako wersjonowane SQL w aplikacji – ale starannie parametryzowane i testowane.

    Decydujące jest nie „gdzie”, lecz żeby wdrożenia, rollbacki i zależności były jasne.

    Diagnostyka błędów: od tekstu wyjątku do sygnału operacyjnego

    Wiele aplikacji loguje tylko „Błąd podczas zapisu”. Dla działu operacyjnego i wsparcia 2. poziomu to bezużyteczne. Modernizacja oznacza: ustrukturyzowane informacje o błędach, bez ujawniania danych wrażliwych. Sensowne elementy logu to:

    • Korelacja: Request-ID lub ID operacji, aby łączyć wpisy logu.
    • Kontekst techniczny: serwer/instancja, baza danych, typ logowania, sterownik, czas trwania.
    • Klasa SQL: nazwa zapytania/przypadku użycia, niekoniecznie pełny tekst SQL.
    • Kategoria błędu: timeout, deadlock, naruszenie ograniczenia (constraint), sieć, logowanie.

    Dzięki temu w praktyce różnica między „widzimy tylko objawy” a „możemy precyzyjnie zawęzić przyczyny” staje się znacząca.

    Zmiany schematu i danych: uczynić migracje planowalnymi

    Kto modernizuje integrację z SQL Server, niemal zawsze dotyka również schematu: typów danych, indeksów, ograniczeń (constraints), collation lub wprowadzenia nowych tabel dla integracji. Bez dyscypliny migracyjnej powstaje kruche środowisko, które działa na systemie testowym, ale zawodzi w stagingu/produkcji.

    Wersjonowane migracje bazy danych zamiast ręcznych ingerencji

    Solidne podejście to traktowanie zmian bazy danych jak wydań aplikacji: wersjonowane, powtarzalne, z jasnymi warunkami wstępnymi. To może odbywać się przez skrypty migracyjne, pakiet wdrożeniowy lub job wydania. Ważne nie jest narzędzie, lecz zasada:

    • Brak „ręcznych zmian” w produkcji bez możliwości odtworzenia.
    • Strategia rollback przynajmniej dla krytycznych zmian (lub wyraźniejszy „plan tylko do przodu”).
    • Środowisko staging, które realistycznie odzwierciedla dane produkcyjne (maskowanie, jeśli konieczne).

    Typy danych i Unicode: unikać ukrytych błędów

    Szczególnie w starszych Delphi-aplikacjach historyczne założenia (ANSI-Strings, stare collations) spotykają się z nowymi wymaganiami (Unicode, wielojęzyczność, nowi klienci). Po stronie SQL Server standardem są typy NVARCHAR/Unicode. Modernizacja oznacza tu świadome określenie, jak działa kodowanie znaków, sortowanie i porównywanie. W przeciwnym razie powstają trudno odtwarzalne błędy przy wyszukiwaniu, sprawdzaniu duplikatów lub eksportach do interfejsów.

    Architektura: odseparować dostęp do danych i otworzyć go na interfejsy

    W wielu firmach aplikacja Delphi nie jest już jedynym konsumentem danych: portale, zewnętrzni dostawcy usług, BI, DMS czy integracje ERP korzystają z tych samych danych. Jeśli modernizuje się podłączenie do bazy danych, to dobry moment, by ukierunkować architekturę tak, aby wspierała wzrost.

    Warstwy (Layering): wyraźne granice między UI, logiką domenową i dostępem do danych

    Sprawdzonym wzorcem jest architektura warstwowa (np. prezentacja, logika domenowa, dostęp do danych). Brzmi abstrakcyjnie, ale ma bardzo konkretne efekty w eksploatacji:

    • Zmiany są bardziej lokalne: nowe pole nie wymaga 20 zmian formularzy z wbudowanymi zapytaniami SQL.
    • Możliwe stają się testy: logika domenowa może działać na danych testowych bez połączenia z prawdziwą bazą.
    • Security można wdrożyć centralnie: logowanie, sprawdzanie uprawnień, parametryzacja.

    Dla późniejszych kroków, takich jak Delphi REST-API lub Delphi REST-API i REST-serwer ta separacja jest podstawą: wówczas nie „otwiera się bazę danych w internecie”, lecz zdefiniowane przypadki użycia udostępnia się jako interfejs.

    Równoległa eksploatacja: kontrolowane mieszanie starych i nowych dostępów do danych

    W praktyce nie zawsze da się przełączyć wszystko „Big Bang”. Pragmatyczne podejście to uruchamianie nowych dostępów danych zgodnie z nowym standardem, podczas gdy stare moduły nadal funkcjonują. Ważne przy tym:

    • Jednolite reguły transakcyjne, aby dwie technologie nie pracowały przeciwko sobie.
    • Wspólna konfiguracja (serwery, DB, szyfrowanie, time-outy) z jednego źródła.
    • Wyraźne granice migracji: per przypadek użycia lub moduł, a nie „trochę tu i tam”.

    Eksploatacja i administracja: konfiguracja, monitoring, proces wydawania

    Zmodernizowane podłączenie do SQL Server jest „gotowe” dopiero wtedy, gdy działa poprawnie w eksploatacji: parametry są odtwarzalne, logi czytelne, wydania planowane, a monitoring pokazuje nie tylko obciążenie CPU, lecz także problemy aplikacyjne.

    Konfiguracja: powtarzalna i specyficzna dla środowiska

    Pomiędzy developmentem, testem, staging i produkcją różnią się nazwy serwerów, certyfikaty, uwierzytelnianie, a czasem nawet nazwy baz danych. Nie powinno się tego rozwiązywać przez zmiany w kodzie, lecz przez jasną strategię konfiguracji (plik, secret-store, parametry deploymentu). Kluczowe jest: ten sam build, inna konfiguracja – oraz mechanizm, który wcześnie wykryje błędne ustawienia.

    Monitoring: metryki aplikacji uzupełniają metryki SQL Server

    SQL Server oferuje wiele możliwości diagnostycznych (Wait Stats, Query Store, analizy blokowań). Aby uzyskać pełny obraz, potrzebne są jednak także metryki aplikacyjne: czasy odpowiedzi dla poszczególnych scenariuszy użycia, wskaźniki błędów, liczba równoległych operacji na bazie danych, ponowne próby po deadlockach. Dzięki temu osoby odpowiedzialne w IT mogą zdecydować, czy problem pochodzi z bazy danych, sieci czy aplikacji.

    Proces wydania: baza danych i aplikacja traktowane łącznie

    Gdy aplikacja Delphi i baza danych są wdrażane oddzielnie, pojawiają się typowe błędy: nowa aplikacja oczekuje nowej kolumny, migracja bazy danych nie została jeszcze rozprowadzona (lub odwrotnie). Nowoczesny proces wydania definiuje zatem:

    • Kolejność (np. migracja najpierw, aplikacja później),
    • Okno kompatybilności (wersje aplikacji mogą przez pewien czas działać ze starym schematem),
    • Testy weryfikacyjne po wdrożeniu (logowanie, kluczowe scenariusze użycia, operacja zapisu).

    Redukcja ryzyka w projektach: jak modernizować bez przestojów

    Technicznie wiele jest możliwe, ale rzeczywistość projektowa to: ograniczone okna konserwacyjne, słabe pokrycie testami, system musi dalej działać. Sprawdza się podejście etapowe.

    Plan etapów, który działa w środowiskach istniejących

    1. Ustalenie bazy (Baseline): dokumentowanie aktualnych wzorców błędów, timeoutów, najważniejszych zapytań (Top-Queries), konfiguracji serwera.
    2. Zdefiniowanie standardu konfiguracji: reguły Connection-String, TLS/Trust-Policy, czasy oczekiwania (Timeouts), Application Name.
    3. Wprowadzić nowy dostęp do danych: FireDAC (lub wybrany standard) jako zdefiniowana warstwa, najpierw dla wybranych scenariuszy użycia.
    4. Poprawić diagnostykę: logowanie, korelacja, kategorie błędów, opcjonalne funkcje śledzenia SQL w przypadku wsparcia.
    5. Stopniowe zastępowanie: migracja modułów, uzupełnianie testów regresyjnych, usuwanie starych ścieżek.
    6. Wzmocnienie bezpieczeństwa i eksploatacja: monitoring, procesy releaseowe, finalizacja koncepcji uprawnień.

    Istotne: każdy etap przynosi samodzielną wartość. Dzięki temu modernizacja jest uzasadniona nawet wtedy, gdy nie można od razu objąć całego systemu.

    Wnioski końcowe: nowoczesne podłączenie do SQL Server to projekt operacyjny, a nie czysta refaktoryzacja

    Modernizacja podłączenia SQL Server w Delphi to więcej niż wymiana komponentów. Obejmuje poziom bezpieczeństwa, zdolność diagnostyczną, stabilność wydań oraz pytanie, jak dobrze oprogramowanie biznesowe poradzi sobie z rosnącymi wymaganiami. Kto świadomie standaryzuje strategię sterowników, uwierzytelnianie, projekt transakcji i logowanie, redukuje ryzyka operacyjne i tworzy podstawę dla późniejszych kroków, takich jak interfejsy REST, integracje portali lub stopniowa modernizacja Delphi.

    Jeśli chcą Państwo technicznie odpornego dalszego rozwoju istniejącego środowiska Delphi i strukturalnej modernizacji podłączenia do SQL Server, prosimy o kontakt:

    W obszarze merytorycznym ważną rolę odgrywają także Delphi FireDAC SQL Server oraz Delphi zastąpienie Ado, gdy integracje, przepływy danych i dalszy rozwój muszą ze sobą ściśle współgrać.

    Omówić projekt lub przedsięwzięcie modernizacyjne z Net-Base.

    Następny krok

    Gdy temat stanie się rzeczywistym projektem, architekturę, stan istniejący i eksploatację należy wcześnie rozpatrywać wspólnie.

    Wspieramy nie tylko w pojedynczych zagadnieniach, lecz także wtedy, gdy z fragmentów kodu źródłowego, kwestii związanych z systemami legacy lub koncepcji portalu ma powstać solidny projekt dla przedsiębiorstwa.

    • Stan istniejący, obraz docelowy i ryzyka techniczne są oceniane łącznie.
    • REST, dostęp do danych, portale i Rollout nie są odkładane na później.
    • Wcześnie widzą Państwo, która droga jest ekonomicznie opłacalna i operacyjnie wykonalna.

    Udostępnij wpis

    Udostępnij ten wpis bezpośrednio

    LinkedIn, X, XING, Facebook, WhatsApp i e‑mail są natychmiast dostępne. Dla Instagrama przygotowujemy od razu link i krótki tekst.

    E-mail

    Instagram otwiera się w nowej karcie. Link i krótki tekst są wcześniej kopiowane do schowka.