Mysql
 sql >> база данни >  >> RDS >> Mysql

Защо Rails добавя `OR 1=0` към заявки, използвайки хеш синтаксиса на клаузата where с диапазон?

Въз основа на факта, който сте открили, че [1..5] не е правилният начин за определяне на диапазона... Открих защо [1..5] се държи както го прави. За да стигна до там, първо открих, че празен масив в хеш условие произвежда 1=0 SQL условие:

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

И ако проверите ActiveRecord::PredicateBuilder::ArrayHandler код , ще видите, че стойностите на масива винаги са разделени на диапазони и други стойности.

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

Това обяснява защо не виждате 1=0 когато се използват стойности извън диапазона. Това е единственият начин да получите 1=0 от масив без включването на диапазон е да се предостави празен масив, който дава 1=0 състояние, както е показано по-горе. И когато целият масив има в него е диапазон, вие ще получите условията за диапазон (ranges ) и отделно условие за празен масив (values ) изпълнен. Предполагам, че няма основателна причина за това... просто е по-лесно да оставим това да бъде, отколкото да го избегнем (тъй като наборът от резултати е еквивалентен и в двата случая). Ако кодът на дяла беше малко по-интелигентен, тогава нямаше да се налага да използва допълнителните празни values масив и може да пропусне 1=0 състояние.

Що се отнася до къде е 1=0 идва от на първо място... Мисля, че идва от адаптера на базата данни, но не можах да намеря точно къде. Въпреки това бих го нарекъл опит да не се намери запис. С други думи, WHERE 1=0 никога няма да върне потребители, което има смисъл спрямо алтернативен SQL като WHERE id=null който ще намери всички потребители, чийто идентификатор е нулев (осъзнавайки, че това всъщност не е правилен SQL синтаксис). И това е, което бих очаквал, когато се опитвам да намеря всички потребители, чийто идентификатор е в празния набор (т.е. ние не искаме нулеви идентификатори или нулеви идентификатори или каквото и да било). Така че, според мен, оставям малкото за това къде точно 1=0 идва от като черна кутия е ОК. Сега поне можем да разсъждаваме защо диапазонът вътре в масива го кара да се показва!

АКТУАЛИЗИРАНЕ

Също така открих, че дори когато използвате ARel директно, все още можете да получите 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. MySQL заявката с множество оператори И изглежда игнорира един

  2. Как да решите MySQL innodb Изчакване за заключване на метаданни на таблицата на TRUNCATE TABLE?

  3. Създайте база данни в Shell Script - конвертирайте от PHP

  4. mysql_fetch_row() срещу mysql_fetch_assoc() срещу mysql_fetch_array()

  5. Изберете с помощта на динамично генерирано име на таблица