sql >> Databáze >  >> RDS >> Mysql

Proč Rails přidává `OR 1=0` k dotazům pomocí syntaxe hash klauzule where s rozsahem?

Na základě skutečnosti, kterou jste objevili, že [1..5] není správný způsob, jak specifikovat rozsah... Zjistil jsem proč [1..5] chová se tak, jak se chová. Abych se tam dostal, nejprve jsem zjistil, že prázdné pole v hašovací podmínce vytváří 1=0 SQL podmínka:

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

A pokud zkontrolujete Kód ActiveRecord::PredicateBuilder::ArrayHandler , uvidíte, že hodnoty pole jsou vždy rozděleny do rozsahů a dalších hodnot.

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

To vysvětluje, proč nevidíte 1=0 při použití hodnot mimo rozsah. To je jediný způsob, jak získat 1=0 z pole bez zahrnutí rozsahu je poskytnout prázdné pole, které dává 1=0 stavu, jak je uvedeno výše. A když všechno pole má rozsah, dostanete podmínky rozsahu (ranges ) a samostatně podmínku prázdného pole (values ) popraven. Hádám, že pro to není dobrý důvod... prostě je jednodušší to nechat být, než se tomu vyhnout (protože výsledná sada je v obou případech ekvivalentní). Pokud by byl kód oddílu o něco chytřejší, nemusel by se zaměřovat na další prázdné values pole a mohl by přeskočit 1=0 podmínka.

Pokud jde o to, kde 1=0 pochází z prvního místa... Myslím, že pochází z databázového adaptéru, ale nemohl jsem najít přesně kde. Nazval bych to však snahou o neúspěšné nalezení záznamu. Jinými slovy WHERE 1=0 nikdy nevrátí žádné uživatele, což dává smysl oproti alternativním SQL, jako je WHERE id=null který najde všechny uživatele, jejichž id je null (s vědomím, že to není ve skutečnosti správná syntaxe SQL). A to bych očekával při pokusu o nalezení všech uživatelů, jejichž ID je v prázdné sadě (tj. nepožadujeme nulová id nebo nulová id nebo cokoli jiného). Takže, v mé mysli, ponechám bit o tom, kde přesně 1=0 pochází z jako černá skříňka je v pořádku. Přinejmenším nyní můžeme uvažovat o tom, proč rozsah uvnitř pole způsobuje jeho zobrazení!

AKTUALIZACE

Také jsem zjistil, že i když používáte přímo ARel, stále můžete získat 1=0 :

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


  1. COALESCE Funkce v TSQL

  2. Driver.getConnection se zablokuje pomocí ovladače SQLServer a Java 1.6.0_29

  3. Nelze najít sloupec dbo nebo uživatelem definovanou funkci nebo agregaci dbo.Splitfn nebo je název nejednoznačný

  4. Výběr procesoru pro SQL Server 2012