Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dlaczego Railsy dodają `OR 1=0` do zapytań używając składni hash klauzuli WHERE z zakresem?

Opierając się na fakcie, który odkryłeś, że [1..5] nie jest właściwym sposobem określenia zakresu... Odkryłem, dlaczego [1..5] zachowuje się tak, jak to robi. Aby się tam dostać, najpierw odkryłem, że pusta tablica w warunku hash daje 1=0 Warunek SQL:

User.where(id: []).to_sql
# => "SELECT \"users\".* FROM \"users\"  WHERE 1=0"

A jeśli sprawdzisz Kod ActiveRecord::PredicateBuilder::ArrayHandler , zobaczysz, że wartości tablicy są zawsze podzielone na zakresy i inne wartości.

ranges, values = values.partition { |v| v.is_a?(Range) }

To wyjaśnia, dlaczego nie widzisz 1=0 podczas korzystania z wartości spoza zakresu. To jest jedyny sposób na uzyskanie 1=0 z tablicy bez uwzględnienia zakresu jest dostarczenie pustej tablicy, co daje w wyniku 1=0 warunek, jak pokazano powyżej. A kiedy cała tablica ma w sobie zakres, otrzymasz warunki zakresu (ranges ) i osobno warunek pustej tablicy (values ) wykonane. Domyślam się, że nie ma ku temu dobrego powodu… po prostu łatwiej jest na to pozwolić, niż tego uniknąć (ponieważ zestaw wyników jest równoważny w każdym przypadku). Gdyby kod partycji był nieco mądrzejszy, nie musiałby dodawać dodatkowych, pustych values tablica i może pominąć 1=0 stan.

Co do miejsca, w którym 1=0 pochodzi w pierwszej kolejności... Myślę, że pochodzi z adaptera bazy danych, ale nie mogłem znaleźć dokładnie gdzie. Nazwałbym to jednak próbą nietrafienia w odnalezienie rekordu. Innymi słowy, WHERE 1=0 nigdy nie zwróci żadnych użytkowników, co ma sens w przypadku alternatywnego SQL, takiego jak WHERE id=null który znajdzie wszystkich użytkowników, których id jest null (zdając sobie sprawę, że nie jest to poprawna składnia SQL). I tego oczekiwałbym, próbując znaleźć wszystkich użytkowników, których id znajduje się w pustym zestawie (tzn. nie prosimy o nil ids lub null ids lub cokolwiek). Tak więc, moim zdaniem, zostawiam fragment o tym, gdzie dokładnie 1=0 pochodzi jak czarna skrzynka jest OK. Przynajmniej możemy teraz wyjaśnić, dlaczego zakres wewnątrz tablicy powoduje jej pojawienie się!

AKTUALIZACJA

Odkryłem również, że nawet przy bezpośrednim użyciu ARel nadal możesz uzyskać 1=0 :

User.arel_table[:id].in([]).to_sql
# => "1=0"


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dwie kolumny jako klucze podstawowe w mysql?

  2. liczba duplikatów mysql

  3. Nie można pobrać wartości, którą chciałem wybrać za pomocą procedury przechowywanej

  4. sprawdź wiek przed zarejestrowaniem użytkownika, aby sprawdzić, czy ma więcej niż określony wiek za pomocą mvc

  5. Hibernacja:zamieszanie związane z samodołączaniem?