2010-09-25 3 views
2

dans des rails 3.0.0, la requête suivante fonctionne très bien:Rails 3 requête soulève exception lorsque COMME utilisant un double deux points et un point

Author.where("name LIKE :input",{:input => "#{params[:q]}%"}).includes(:books).order('created_at') 

Cependant, quand je l'entrée en tant que chaîne de recherche (donc contenant un double deux points suivi d'un point):

aa: .bb

Je reçois l'exception suivante:

ActiveRecord :: StatementInvalid: SQLite3 :: SQLException: nom de la colonne ambiguë: created_at

Dans les journaux la ce sont les requêtes SQL:

with aa as input: 
Author Load (0.4ms) SELECT "authors".* FROM "authors" WHERE (name LIKE 'aa%') ORDER BY created_at 
Book Load (2.5ms) SELECT "books".* FROM "books" WHERE ("books".author_id IN (1,2,3)) ORDER BY id 

with aa:.bb as input: 
SELECT DISTINCT "authors".id FROM "authors" LEFT OUTER JOIN "books" ON "books"."author_id" = "authors"."id" WHERE (name LIKE 'aa:.bb%') ORDER BY created_at DESC LIMIT 12 OFFSET 0 
SQLite3::SQLException: ambiguous column name: created_at 

Il semble que le aa: .bb En entrée, une requête supplémentaire est effectuée pour récupérer les id_s de l'auteur distinct. Je pensais que Rails échapperait à tous les caractères. Est-ce un comportement attendu ou un bug?

Cordialement,

Pieter

Répondre

1

L'erreur « colonne ambiguë » se produit généralement lorsque vous utilisez inclut ou jointures et ne spécifiez pas quelle table vous faites référence:

"name LIKE :input" 

Devrait être:

"authors.name LIKE :input" 

Juste "nom" est ambigu si vos livres tabl e a une colonne de nom aussi.

Aussi: jetez un oeil à votre développement.log pour voir à quoi ressemble la requête générée. Cela vous montrera si c'est échappé correctement.

+0

J'ai oublié de mentionner que la colonne 'created_at' provoque l'exception ambiguë. Je comprends votre point, et c'est une bonne astuce, mais c'est vraiment étrange que cela se produit uniquement lorsque j'introduis un mot: .otherword comme la requête de recherche – Pieter

+1

right, j'ai raté ça: l'ambiguïté est dans la clause ORDER. Vous devriez regarder votre journal pour voir la requête SQL générée pour être sûr que rien de drôle ne se passe. –

+1

Andrew, j'ai ajouté la sortie du journal. Il semble qu'avec l'entrée aa: .bb, une requête supplémentaire soit faite pour déterminer les author_ids distincts, pour aller chercher les livres. Et cette requête soulève l'exception. Ce n'est pas un problème à commander sur 'houses.created_at' au lieu de simplement 'created_at', mais ça m'inquiète que ça ressemble à:. pourrait conduire à une attaque sql? – Pieter

0

Rails a 2 versions de includes: Une qui construit une grande requête avec des jointures (la 2ème de vos 2 requêtes et donc plus susceptible d'aboutir à des références de colonnes ambiguës et qui évite les jointures en faveur d'une requête séparée par association Rails décide de la stratégie à utiliser en fonction du fait qu'il pense que vos conditions, votre ordre, etc. se réfèrent aux tables incluses (puisque dans ce cas, la version des jointures est requise.) Lorsqu'une condition est un fragment de chaîne, heuristique isn ' t très sophistiqué - il me semble me rappeler qu'il ne fait que balayer les conditions de tout ce qui pourrait ressembler à une colonne d'une autre table (ex: foo.bar) donc avoir un littéral de cette forme pourrait le tromper

Vous pouvez soit qualifier vos noms de colonne afin que cela n'a pas d'importance quelle stratégie est utilisée ou vous pouvez utiliser preload/eager_load au lieu d'includes. Ceux-ci se comportent de la même manière que l'inclusion mais forcent une stratégie d'inclusion spécifique plutôt que d'essayer de deviner lequel est le plus approprié.

1

Remplacer

.includes(:books) 

avec

.preload(:books) 

Cela devrait forcer activerecord à utiliser 2 requêtes au lieu de la jointure.

Questions connexes