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"