sql >> Databasteknik >  >> RDS >> Mysql

Varför lägger Rails till `OR 1=0` till frågor med hjälp av where-satsens hash-syntax med ett intervall?

Bygger på det faktum, som du har upptäckt, att [1..5] är inte det korrekta sättet att specificera intervallet... Jag har upptäckt varför [1..5] beter sig som den gör. För att komma dit upptäckte jag först att en tom array i ett hashtillstånd producerar 1=0 SQL-villkor:

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

Och om du kollar ActiveRecord::PredicateBuilder::ArrayHandler-kod , kommer du att se att matrisvärden alltid är uppdelade i intervall och andra värden.

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

Detta förklarar varför du inte ser 1=0 när man använder icke-intervallvärden. Det vill säga det enda sättet att få 1=0 från en array utan att inkludera ett intervall är att tillhandahålla en tom array, vilket ger 1=0 skick, som visas ovan. Och när allt som arrayen har i sig är ett intervall kommer du att få räckviddsvillkoren (ranges ) och, separat, ett tomt arrayvillkor (values ) avrättade. Min gissning är att det inte finns någon bra anledning till detta... det är helt enkelt lättare att låta detta vara än att undvika det (eftersom resultatuppsättningen är likvärdig i båda riktningarna). Om partitionskoden var lite smartare så skulle den inte behöva ta tag i de ytterligare tomma values array och kunde hoppa över 1=0 skick.

När det gäller var 1=0 kommer från i första hand... Jag tror att det kommer från databasadaptern, men jag kunde inte hitta exakt var. Jag skulle dock kalla det ett försök att misslyckas med att hitta en skiva. Med andra ord, WHERE 1=0 kommer aldrig att returnera några användare, vilket är vettigt framför alternativ SQL som WHERE id=null som kommer att hitta alla användare vars id är null (inser att detta inte riktigt är korrekt SQL-syntax). Och det här är vad jag förväntar mig när jag försöker hitta alla användare vars id finns i den tomma uppsättningen (dvs. vi ber inte om noll-ID eller noll-ID eller vad som helst). Så, i mitt sinne, lämnar jag lite om exakt var 1=0 kommer från som en svart låda är OK. Nu kan vi åtminstone resonera om varför räckvidden inuti arrayen får den att dyka upp!

UPPDATERA

Jag har också upptäckt att även när du använder ARel direkt kan du fortfarande få 1=0 :

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


  1. SQL Server AlwaysOn Tillgänglighetsgrupper:Installation och konfiguration, del 2

  2. Hur man lägger till en filgrupp till en SQL Server-databas (T-SQL)

  3. Hur APPROX_COUNT_DISTINCT() fungerar i SQL Server

  4. PHP PDO vs normal mysql_connect