Почему параметры, передаваемые в activerecord, могут вызывать ошибки псевдонимов таблиц? - PullRequest
0 голосов
/ 04 августа 2011

Я выполняю довольно сложный (и, по общему признанию, довольно уродливый) запрос как часть страницы поиска администратора.Он работает как задумано, пока параметр поиска не включает в себя.в этом например.foo@bar.com ломает его, foo @ bar - нет.Запрос строится следующим образом:

 DealPurchase.order('created_at DESC').includes(
      :couple => :couple_detail, :vendor => :vendor_detail
    ).joins(:couple => :couple_detail).joins(:vendor => :vendor_detail).joins(
      "LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id"
    ).where(
      "CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE ? OR " +
      "vendor_detail.business_name LIKE ? OR " +
      "users.email LIKE ? OR " +
      "coupons.coupon_code LIKE ? OR " +
      "deal_purchases.voucher_code LIKE ?", 
      "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%"
    ).includes(:coupon)

Когда сгенерированный запрос работает, он выглядит следующим образом:

SELECT `deal_purchases`.* FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%keifatosweet@hotmail%' OR vendor_detail.business_name LIKE '%keifatosweet@hotmail%' OR users.email LIKE '%keifatosweet@hotmail%' OR coupons.coupon_code LIKE '%keifatosweet@hotmail%' OR deal_purchases.voucher_code LIKE '%keifatosweet@hotmail%') ORDER BY created_at DESC

Когда params [: search] включает a.это выглядит так:

SELECT `deal_purchases`.`id` AS t0_r0, `deal_purchases`.`couple_id` AS t0_r1, `deal_purchases`.`vendor_id` AS t0_r2, `deal_purchases`.`deal_id` AS t0_r3, `deal_purchases`.`transaction_id` AS t0_r4, `deal_purchases`.`voucher_code` AS t0_r5, `deal_purchases`.`created_at` AS t0_r6, `deal_purchases`.`updated_at` AS t0_r7, `deal_purchases`.`credit_card_id` AS t0_r8, `deal_purchases`.`used` AS t0_r9, `deal_purchases`.`paid` AS t0_r10, `deal_purchases`.`refunded` AS t0_r11, `deal_purchases`.`cents_spent` AS t0_r12, `deal_purchases`.`weddingful_cents_spent` AS t0_r13, `deal_purchases`.`weddingful_cents_awarded` AS t0_r14, `deal_purchases`.`affiliate_id` AS t0_r15, `deal_purchases`.`affiliate_cents` AS t0_r16, `deal_purchases`.`affiliate_link_id` AS t0_r17, `deal_purchases`.`coupon_id` AS t0_r18, `users`.`user_id` AS t1_r0, `users`.`email` AS t1_r1, `users`.`password` AS t1_r2, `users`.`create_date` AS t1_r3, `users`.`last_updated` AS t1_r4, `users`.`last_login` AS t1_r5, `users`.`user_type` AS t1_r6, `users`.`status` AS t1_r7, `users`.`fb_user_id` AS t1_r8, `couple_detail`.`id` AS t2_r0, `couple_detail`.`user_id` AS t2_r1, `couple_detail`.`fname` AS t2_r2, `couple_detail`.`lname` AS t2_r3, `couple_detail`.`fiance_fname` AS t2_r4, `couple_detail`.`fiance_lname` AS t2_r5, `couple_detail`.`phone` AS t2_r6, `couple_detail`.`address1` AS t2_r7, `couple_detail`.`address2` AS t2_r8, `couple_detail`.`city` AS t2_r9, `couple_detail`.`state` AS t2_r10, `couple_detail`.`country` AS t2_r11, `couple_detail`.`zipcode` AS t2_r12, `couple_detail`.`couple_role` AS t2_r13, `couple_detail`.`fiance_role` AS t2_r14, `couple_detail`.`logo` AS t2_r15, `couple_detail`.`status` AS t2_r16, `couple_detail`.`completed_registration` AS t2_r17, `couple_detail`.`weddingful_cents` AS t2_r18, `vendors_deal_purchases`.`user_id` AS t3_r0, `vendors_deal_purchases`.`email` AS t3_r1, `vendors_deal_purchases`.`password` AS t3_r2, `vendors_deal_purchases`.`create_date` AS t3_r3, `vendors_deal_purchases`.`last_updated` AS t3_r4, `vendors_deal_purchases`.`last_login` AS t3_r5, `vendors_deal_purchases`.`user_type` AS t3_r6, `vendors_deal_purchases`.`status` AS t3_r7, `vendors_deal_purchases`.`fb_user_id` AS t3_r8, `vendor_detail`.`id` AS t4_r0, `vendor_detail`.`user_id` AS t4_r1, `vendor_detail`.`business_name` AS t4_r2, `vendor_detail`.`business_phone` AS t4_r3, `vendor_detail`.`first_name` AS t4_r4, `vendor_detail`.`last_name` AS t4_r5, `vendor_detail`.`url` AS t4_r6, `vendor_detail`.`address1` AS t4_r7, `vendor_detail`.`address2` AS t4_r8, `vendor_detail`.`city` AS t4_r9, `vendor_detail`.`state` AS t4_r10, `vendor_detail`.`country` AS t4_r11, `vendor_detail`.`zipcode` AS t4_r12, `vendor_detail`.`business_description` AS t4_r13, `vendor_detail`.`tagline` AS t4_r14, `vendor_detail`.`logo` AS t4_r15, `vendor_detail`.`logo_caption` AS t4_r16, `vendor_detail`.`store_type` AS t4_r17, `vendor_detail`.`vendor_type` AS t4_r18, `vendor_detail`.`signup_pitch_seen` AS t4_r19, `vendor_detail`.`signup_complete` AS t4_r20, `vendor_detail`.`profile_views` AS t4_r21, `vendor_detail`.`hash_key` AS t4_r22, `vendor_detail`.`available_credits` AS t4_r23, `vendor_detail`.`credit_expire_on` AS t4_r24, `vendor_detail`.`promotion_title` AS t4_r25, `vendor_detail`.`promotion_text` AS t4_r26, `vendor_detail`.`promotion_posted_on` AS t4_r27, `vendor_detail`.`notes` AS t4_r28, `vendor_detail`.`last_updated` AS t4_r29, `vendor_detail`.`claim_date` AS t4_r30, `vendor_detail`.`profile_percentage` AS t4_r31, `vendor_detail`.`vendor_url` AS t4_r32, `vendor_detail`.`status` AS t4_r33, `vendor_detail`.`twilio_number` AS t4_r34 FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%@hotmail.com%' OR vendor_detail.business_name LIKE '%@hotmail.com%' OR users.email LIKE '%@hotmail.com%' OR coupons.coupon_code LIKE '%@hotmail.com%' OR deal_purchases.voucher_code LIKE '%@hotmail.com%') ORDER BY created_at DESC

Произошла ошибка:

Mysql2::Error: Not unique table/alias: 'coupons': SELECT  `deal_purchases`.`id` AS t0_r0, `deal_purchases`.`couple_id` AS t0_r1, `deal_purchases`.`vendor_id` AS t0_r2, `deal_purchases`.`deal_id` AS t0_r3, `deal_purchases`.`transaction_id` AS t0_r4, `deal_purchases`.`voucher_code` AS t0_r5, `deal_purchases`.`created_at` AS t0_r6, `deal_purchases`.`updated_at` AS t0_r7, `deal_purchases`.`credit_card_id` AS t0_r8, `deal_purchases`.`used` AS t0_r9, `deal_purchases`.`paid` AS t0_r10, `deal_purchases`.`refunded` AS t0_r11, `deal_purchases`.`cents_spent` AS t0_r12, `deal_purchases`.`weddingful_cents_spent` AS t0_r13, `deal_purchases`.`weddingful_cents_awarded` AS t0_r14, `deal_purchases`.`affiliate_id` AS t0_r15, `deal_purchases`.`affiliate_cents` AS t0_r16, `deal_purchases`.`affiliate_link_id` AS t0_r17, `deal_purchases`.`coupon_id` AS t0_r18, `users`.`user_id` AS t1_r0, `users`.`email` AS t1_r1, `users`.`password` AS t1_r2, `users`.`create_date` AS t1_r3, `users`.`last_updated` AS t1_r4, `users`.`last_login` AS t1_r5, `users`.`user_type` AS t1_r6, `users`.`status` AS t1_r7, `users`.`fb_user_id` AS t1_r8, `couple_detail`.`id` AS t2_r0, `couple_detail`.`user_id` AS t2_r1, `couple_detail`.`fname` AS t2_r2, `couple_detail`.`lname` AS t2_r3, `couple_detail`.`fiance_fname` AS t2_r4, `couple_detail`.`fiance_lname` AS t2_r5, `couple_detail`.`phone` AS t2_r6, `couple_detail`.`address1` AS t2_r7, `couple_detail`.`address2` AS t2_r8, `couple_detail`.`city` AS t2_r9, `couple_detail`.`state` AS t2_r10, `couple_detail`.`country` AS t2_r11, `couple_detail`.`zipcode` AS t2_r12, `couple_detail`.`couple_role` AS t2_r13, `couple_detail`.`fiance_role` AS t2_r14, `couple_detail`.`logo` AS t2_r15, `couple_detail`.`status` AS t2_r16, `couple_detail`.`completed_registration` AS t2_r17, `couple_detail`.`weddingful_cents` AS t2_r18, `vendors_deal_purchases`.`user_id` AS t3_r0, `vendors_deal_purchases`.`email` AS t3_r1, `vendors_deal_purchases`.`password` AS t3_r2, `vendors_deal_purchases`.`create_date` AS t3_r3, `vendors_deal_purchases`.`last_updated` AS t3_r4, `vendors_deal_purchases`.`last_login` AS t3_r5, `vendors_deal_purchases`.`user_type` AS t3_r6, `vendors_deal_purchases`.`status` AS t3_r7, `vendors_deal_purchases`.`fb_user_id` AS t3_r8, `vendor_detail`.`id` AS t4_r0, `vendor_detail`.`user_id` AS t4_r1, `vendor_detail`.`business_name` AS t4_r2, `vendor_detail`.`business_phone` AS t4_r3, `vendor_detail`.`first_name` AS t4_r4, `vendor_detail`.`last_name` AS t4_r5, `vendor_detail`.`url` AS t4_r6, `vendor_detail`.`address1` AS t4_r7, `vendor_detail`.`address2` AS t4_r8, `vendor_detail`.`city` AS t4_r9, `vendor_detail`.`state` AS t4_r10, `vendor_detail`.`country` AS t4_r11, `vendor_detail`.`zipcode` AS t4_r12, `vendor_detail`.`business_description` AS t4_r13, `vendor_detail`.`tagline` AS t4_r14, `vendor_detail`.`logo` AS t4_r15, `vendor_detail`.`logo_caption` AS t4_r16, `vendor_detail`.`store_type` AS t4_r17, `vendor_detail`.`vendor_type` AS t4_r18, `vendor_detail`.`signup_pitch_seen` AS t4_r19, `vendor_detail`.`signup_complete` AS t4_r20, `vendor_detail`.`profile_views` AS t4_r21, `vendor_detail`.`hash_key` AS t4_r22, `vendor_detail`.`available_credits` AS t4_r23, `vendor_detail`.`credit_expire_on` AS t4_r24, `vendor_detail`.`promotion_title` AS t4_r25, `vendor_detail`.`promotion_text` AS t4_r26, `vendor_detail`.`promotion_posted_on` AS t4_r27, `vendor_detail`.`notes` AS t4_r28, `vendor_detail`.`last_updated` AS t4_r29, `vendor_detail`.`claim_date` AS t4_r30, `vendor_detail`.`profile_percentage` AS t4_r31, `vendor_detail`.`vendor_url` AS t4_r32, `vendor_detail`.`status` AS t4_r33, `vendor_detail`.`twilio_number` AS t4_r34, `coupons`.`id` AS t5_r0, `coupons`.`coupon_code` AS t5_r1, `coupons`.`region_id` AS t5_r2, `coupons`.`category_id` AS t5_r3, `coupons`.`expiry` AS t5_r4, `coupons`.`max_uses` AS t5_r5, `coupons`.`deal_id` AS t5_r6, `coupons`.`discount_cents` AS t5_r7, `coupons`.`discount_percent` AS t5_r8, `coupons`.`weddingful_cents_awarded` AS t5_r9, `coupons`.`weddingful_cents_percent` AS t5_r10, `coupons`.`used_count` AS t5_r11, `coupons`.`affiliate_id` AS t5_r12, `coupons`.`created_at` AS t5_r13, `coupons`.`updated_at` AS t5_r14 FROM `deal_purchases` INNER JOIN `users` ON `users`.`user_id` = `deal_purchases`.`couple_id` INNER JOIN `couple_detail` ON `couple_detail`.`user_id` = `users`.`user_id` INNER JOIN `users` `vendors_deal_purchases` ON `vendors_deal_purchases`.`user_id` = `deal_purchases`.`vendor_id` INNER JOIN `vendor_detail` ON `vendor_detail`.`user_id` = `vendors_deal_purchases`.`user_id` LEFT OUTER JOIN `coupons` ON `coupons`.`id` = `deal_purchases`.`coupon_id` LEFT JOIN coupons ON deal_purchases.coupon_id = coupons.id WHERE (CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE '%keifatosweet@hotmail.com%' OR vendor_detail.business_name LIKE '%keifatosweet@hotmail.com%' OR users.email LIKE '%keifatosweet@hotmail.com%' OR coupons.coupon_code LIKE '%keifatosweet@hotmail.com%' OR deal_purchases.voucher_code LIKE '%keifatosweet@hotmail.com%') ORDER BY created_at

Я открыт для рефакторинга способа построения запроса, если у людей есть предложения по улучшению, но что яя действительно ищу способ не взорваться, если параметр поиска включает в себя.Будем весьма благодарны за любые предложения на этот счет.

1 Ответ

1 голос
/ 05 августа 2011

@ Точка зрения Джофокодина заставила меня попытаться переписать то, как я сделал свое левое соединение, чтобы отобразить версию, которую производил rails.

DealPurchase.order('created_at DESC').includes(
  :couple => :couple_detail, :vendor => :vendor_detail
).joins(:couple => :couple_detail).joins(:vendor => :vendor_detail).joins(
  "LEFT OUTER JOIN `coupons` ON `coupons`.`id` = `deal_purchases`.`coupon_id`"
).where(
  "CONCAT_WS(' ', couple_detail.fname, couple_detail.lname) LIKE ? OR " +
  "vendor_detail.business_name LIKE ? OR " +
  "users.email LIKE ? OR " +
  "coupons.coupon_code LIKE ? OR " +
  "deal_purchases.voucher_code LIKE ?", 
  "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%"
).includes(:coupon)

Это сработало, Rails прекратил создание дополнительного предложения соединения для купонов. Хотелось бы, чтобы я понял, что происходит немного лучше, но это, по крайней мере, решает конкретную проблему.

Спасибо за помощь JofoCodin.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...