# Pole wyboru z wpisanym tekstem zamiast identyfikatora i błąd Invalid column name

> Dlaczego urwana fraza z pola wyboru trafiała do zapytania SQL jako nazwa kolumny: jqWidgets nadpisuje val(), a poprawka pilnuje, by identyfikator był liczbą.

Adres strony: https://magazyn.softwarestudio.com.pl/pole-wyboru-z-wpisanym-tekstem-zamiast-identyfikatora-w-zapytaniu/

---

Operator kolektora nie mógł dopisać pozycji do dokumentu wydania, a w rejestrze błędów pojawiały się wpisy „Invalid column name”. Przyczyną był kod JavaScript formularza: pole wyboru zwracało wpisany tekst zamiast identyfikatora odbiorcy. Poprawka pilnuje, by do zapytania trafiała tylko liczba.
Opisujemy błąd z jednego wdrożenia [Studio WMS.net](/wms/), który na kolektorze objawiał się wpisem „Invalid column name” w rejestrze błędów. Przyczyną nie było zapytanie, tylko kod JavaScript formularza. Tekst jest napisany dla działu IT i kierownika projektu i nie zawiera dosłownego kodu z wdrożenia.

Formularz wydania na kolektorze opisuje artykuł o [wydaniu bezpośrednim WZB na kolektorze](https://magazyn.wysokiego.skladowania.pl/wydanie-bezposrednie-wzb-na-kolektorze-android/). Inny cichy błąd, który ujawnił się dopiero przy zatwierdzeniu dokumentu, opisuje artykuł o [procedurze z QUOTED_IDENTIFIER OFF](https://sql.server.net.pl/sql-server/procedura-z-quoted-identifier-off-i-blad-update-przy-zatwierdzeniu/).

## Objaw w rejestrze błędów

Operator kolektora z aplikacją [magazynową Android](/aplikacja-magazynowa-android/) nie mógł dopisać pozycji do dokumentu wydania. W rejestrze błędów pojawiały się wpisy „Invalid column name”, w których nazwą kolumny była urwana fraza wyszukiwania.

Wpisy dotyczyły dwóch zapytań: zapytania zapisującego pozycję i zapytania kontrolnego. Mechanizm działał w zdecydowanej większości przypadków, więc błąd pojawiał się tylko wtedy, gdy operator wpisał frazę i nie wybrał pozycji z listy.

Przyczyną nie była treść zapytania, tylko kod JavaScript formularza. Parametr odbiorcy to identyfikator liczbowy, a zapytanie celowo wstawia go bez apostrofów.

## Co robi val() w jqxComboBox

Biblioteka jqWidgets nadpisuje w jQuery metodę val(). Dla pola jqxComboBox wywołanie zwraca wartość zaznaczonej pozycji, a gdy nic nie zaznaczono, zwraca tekst z pola wejściowego.

Kod formularza widzi więc w obu przypadkach tę samą odpowiedź, choć znaczy ona co innego. Kolejne stany powstają, gdy operator wybierze pozycję, a potem dopisze tekst do pola, albo wpisze ręcznie same cyfry. Tabela zestawia cztery stany pola.

| Stan pola | Co zwraca val() | Co trafia do zapytania |
| --- | --- | --- |
| Wybrano pozycję z listy | Identyfikator liczbowy | Poprawna liczba |
| Wpisano tekst, nie wybrano pozycji | Wpisany tekst | Goły token, czyli nazwa kolumny. Błąd Invalid column name |
| Wybrano pozycję, potem dopisano tekst | Poprzedni wybór | Stary identyfikator. Wariant, który został |
| Wpisano same cyfry bez wyboru | Wpisany ciąg cyfr | Liczba, więc zapytanie działa. Skutek cichy. Wariant, który został |

## Dlaczego tekst stał się nazwą kolumny

Gdy operator wpisał frazę i nie wybrał pozycji z listy, do zapytania trafiał wpisany tekst jako goły token. SQL Server odczytywał go jako nazwę kolumny, bo bez apostrofów to nie literał tekstowy, tylko identyfikator. Błąd nie wynikał więc z uszkodzonych danych w bazie, tylko z wartości przesłanej do zapytania.

Przykład z fikcyjnymi nazwami: operator wpisuje fragment alf, nie wybiera pozycji, a do zapytania trafia ten fragment.

Ta sama słabość była na drugiej ścieżce. Procedura obsługi zamknięcia listy sprawdzała tylko, czy wartość jest niepusta, więc wpisany tekst trafiał także do zapytania kontrolnego.

> Parametr liczbowy wstawiany do zapytania bez apostrofów musi być liczbą. Wpisany tekst staje się wtedy nazwą kolumny.

## Funkcja pilnująca identyfikatora

Poprawka to pomocnicza funkcja, która zwraca wartość tylko wtedy, gdy przechodzi wyrażenie regularne ^[0-9]+$. Wzorzec przepuszcza wyłącznie wartości złożone z cyfr, co wyklucza wpisany tekst. Wpisany ciąg samych cyfr przeszedłby tak samo jak identyfikator, więc kontrola nie dowodzi wyboru z listy. Procedura obsługi zamknięcia listy używa tej funkcji.

Tuż przed zapisem pozycji formularz sprawdza identyfikator odbiorcy. Gdy go brak, pokazuje komunikat „Wybierz odbiorce z listy!” i ustawia fokus na polu. Niczego wtedy nie zapisuje. Pisownię komunikatu podajemy tak, jak ją pokazuje program.

To ostatnia kontrola, a nie pierwsza. W typowym przepływie wpisany tekst cofa operatora do kroku odbiorcy już wcześniej i komunikat się nie pojawia.

Sama zamiana val() na inną metodę odczytu wartości kontrolki niczego by nie naprawiła, bo oba wywołania idą tą samą ścieżką. Sposób zgłaszania błędów w formularzach opisuje artykuł o [komunikatach błędów w WMS](/komunikaty-bledow-w-wms-tekst-dzwiek-i-slownik/).

## Wdrożenie i sprawdzenie poprawki

Wdrożenie wymagało wgrania pliku i podbicia znacznika wersji skryptu w definicji transakcji. Bez tego terminale nadal ładują skrypt z pamięci podręcznej.

Poprawka dotyczy skryptu formularza, a nie zapytań, więc zapytania w bazie zostają bez zmian. Dlatego sprawdzamy dwa miejsca: plik skryptu na serwerze i znacznik wersji w definicji transakcji.

Test porównawczy na produkcji dał dwa wyniki. Przy wpisanym tekście stara ścieżka zwracała ten tekst, a nowa pusty ciąg. Po wyborze z listy obie zwracały identyfikator, więc nic się nie zepsuło.

## Czego świadomie nie zrobiono

Rozważano zabezpieczenie w samym zapytaniu: konwersję TRY_CONVERT z zamianą pustego wyniku na zero. Odrzucono je. Zamieniłoby twardy błąd na cichy zapis pozycji bez odbiorcy, czyli uszkodzony dokument bez żadnego sygnału.

Cichy błąd jest trudniejszy do wykrycia niż wpis w rejestrze, bo nikt nie dostaje sygnału. Dlatego walidacja stoi przed wysłaniem pozycji, a zapytanie zachowuje się jak dotąd.

## Wariant, który został

Dwóch wariantów poprawka nie obejmuje. W pierwszym operator wybiera pozycję z listy, a potem dopisuje tekst do pola. Kontrolka nadal zwraca poprzedni wybór, więc walidacja przepuszcza stary identyfikator. Dokument dostaje wtedy odbiorcę wybranego wcześniej, a nie tego, którego fragment widać w polu.

W drugim operator wpisuje ręcznie same cyfry i nie wybiera pozycji. Funkcja zwraca ten ciąg tak samo jak identyfikator, a do zapytania trafia on jako liczba. Zapytanie działa, więc nie ma błędu w rejestrze, a dokument może dostać przypadkowego odbiorcę. Skutek jest cichy.

Uwaga na przyszłość dotyczy bardzo dużych identyfikatorów. JavaScript zaokrągla duże liczby całkowite powyżej pewnego progu, więc odczytany identyfikator mógłby wskazać innego, istniejącego odbiorcę. Dotychczasowe identyfikatory mieszczą się poniżej tego progu.

## Pytania do zadania na etapie analizy

Przed wdrożeniem formularzy z polami wyboru zadajemy cztery pytania. To pytania, a nie fakty o opisywanym wdrożeniu. Zakres analizy opisuje artykuł o [analizie przedwdrożeniowej WMS](/analiza-przedwdrozeniowa-wms-co-zawiera/).

- Które pola wstawiają wartość do zapytania - i czy parametr jest liczbą, czy tekstem.
- Co widzi operator bez wyboru - komunikat przy polu i brak zapisu.
- Gdzie trafiają błędy zapytań - kto przegląda rejestr błędów i jak często.
- Jak wdrażamy zmianę skryptu - czy znacznik wersji w definicji transakcji zmienia się razem z plikiem.

Pola formularzy i ich kontrole uzgadnia się w [specyfikacji formularzy w arkuszu](/specyfikacja-formularzy-wms-w-arkuszu/).

## Czego ta strona nie opisuje

Strona opisuje mechanizm błędu, a nie nazwy plików, funkcji ani zapytań z wdrożenia. Nie podajemy liczby operatorów ani liczby wystąpień wpisów. Opis dotyczy formularza jednego magazynu klienta, a nie standardowej funkcji Studio WMS.net.

## Pytania i odpowiedzi o polu wyboru i błędzie Invalid column name

## Słownik pojęć o polu wyboru i identyfikatorze w zapytaniu

Terminy używane przez dział IT i kierownika projektu, gdy pole wyboru w formularzu WMS zwraca tekst zamiast identyfikatora.
