Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum fügt Rails "OR 1=0" zu Abfragen hinzu, die die Hash-Syntax der Where-Klausel mit einem Bereich verwenden?

Aufbauend auf der Tatsache, die Sie entdeckt haben, dass [1..5] ist nicht die richtige Art, den Bereich anzugeben ... Ich habe herausgefunden, warum [1..5] verhält sich so wie es ist. Um dorthin zu gelangen, habe ich zuerst festgestellt, dass ein leeres Array in einer Hash-Bedingung den 1=0 erzeugt SQL-Bedingung:

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

Und wenn Sie den ActiveRecord::PredicateBuilder::ArrayHandler-Code , werden Sie sehen, dass Array-Werte immer in Bereiche und andere Werte unterteilt sind.

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

Dies erklärt, warum Sie 1=0 nicht sehen bei Verwendung von Werten außerhalb des Bereichs. Das ist die einzige Möglichkeit, 1=0 zu bekommen aus einem Array ohne Angabe eines Bereichs besteht darin, ein leeres Array zu liefern, was den 1=0 ergibt Zustand, wie oben gezeigt. Und wenn alles, was das Array enthält, ein Bereich ist, erhalten Sie die Bereichsbedingungen (ranges ) und separat eine leere Array-Bedingung (values ) hingerichtet. Meine Vermutung ist, dass es dafür keinen guten Grund gibt ... es ist einfach einfacher, dies zuzulassen, als es zu vermeiden (da die Ergebnismenge in beiden Fällen gleichwertig ist). Wenn der Partitionscode etwas intelligenter wäre, müsste er die zusätzlichen, leeren values nicht anhängen Array und könnte 1=0 überspringen Zustand.

Was den 1=0 betrifft kommt von in erster Linie ... Ich denke, das kommt vom Datenbankadapter, aber ich konnte nicht genau finden, wo. Ich würde es jedoch einen Versuch nennen, keine Aufzeichnungen zu finden. Mit anderen Worten, WHERE 1=0 wird niemals Benutzer zurückgeben, was gegenüber alternativem SQL wie WHERE id=null sinnvoll ist wodurch alle Benutzer gefunden werden, deren ID null ist (wobei erkannt wird, dass dies nicht wirklich die korrekte SQL-Syntax ist). Und das würde ich erwarten, wenn ich versuche, alle Benutzer zu finden, deren ID in der leeren Menge ist (d. H. Wir fragen nicht nach Null-IDs oder Null-IDs oder was auch immer). Also, in meinen Gedanken, lass das Bit genau dort, wo 1=0 kommt aus wie eine Blackbox ist OK. Zumindest können wir jetzt darüber nachdenken, warum der Bereich innerhalb des Arrays dafür sorgt, dass es angezeigt wird!

AKTUALISIEREN

Ich habe auch festgestellt, dass Sie selbst bei direkter Verwendung von ARel immer noch 1=0 erhalten können :

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