2010-06-28 59 views
0

我得到這個錯誤時沒有錯誤:Python的DataError從存儲過程的到來,但手動運行

DataError: (DataError) invalid input syntax for integer: 
"1.50" CONTEXT: PL/pgSQL function "sp_aggregate_cart" line 82 
at FOR over EXECUTE statement 
'SELECT total_items, subtotal, is_shipping_required, discount_other, 
is_shipping_discount FROM sp_aggregate_cart(8135)' {} 

當運行我的應用程序代碼。當我手動運行該查詢時,一切都很好。我碰巧知道1.50在這個例子中,它是一個通過聲明爲數字(10,2)的函數中的變量傳遞的值。它不被函數返回,只是被處理。

此查詢如何在應用程序代碼中引發此錯誤,但在pgadmin中運行良好?

好的,這裏是存儲過程。 discount_amount是您看到錯誤的1.50。

CREATE TYPE buy_object_info as (object_id integer, promo_id integer, buy_quantity integer, get_quantity integer, quantity integer, discount_amount numeric(10,2)); 

-- Function: sp_aggregate_cart(integer) 

DROP FUNCTION sp_aggregate_cart(integer); 

CREATE OR REPLACE FUNCTION sp_aggregate_cart(p_cart_id integer) 
    RETURNS SETOF cart AS 
$BODY$ 
DECLARE 
    v_total_items int; 
    v_subtotal numeric; 
    v_discount_other record; 
    v_items_shipping integer; 
    v_shipping_required boolean; 
    buy_object_info buy_object_info%rowtype; 
    buy_object_price numeric; 
    buy_object_orginal_subtotal numeric; 
    other_promo_id integer; 
    buy_object_query text; 
    other_promo_buy_quantity integer; 
    BEGIN 
    -- Get the total number of items 
    SELECT sum(quantity) INTO v_total_items FROM cart_object WHERE cart_id = p_cart_id; 

    -- Get the subtotal 
    SELECT sum(unit_price) INTO v_subtotal FROM (
     SELECT co.cart_id, co.object_id, co.quantity, 
      CASE 
       --When buy only cart quantity = buy quantity 
       WHEN (p.get_quantity = 0 or p.get_quantity IS NULL) AND (p.buy_quantity > 0 OR p.buy_quantity IS NOT NULL) AND pbo.object_id = co.object_id AND p.buy_quantity = co.quantity 
        THEN ((cast(oa.value AS numeric(10,2)) - COALESCE(pco.discount_amount, 0)) * p.buy_quantity) 
       --When buy only more than the buy quantity in cart 
       WHEN (p.get_quantity = 0 or p.get_quantity IS NULL) AND (p.buy_quantity > 0 OR p.buy_quantity IS NOT NULL) AND pbo.object_id = co.object_id AND p.buy_quantity < co.quantity 
        THEN (((cast(oa.value AS numeric(10,2)) - COALESCE(pco.discount_amount, 0))) * p.buy_quantity) + ((co.quantity - p.buy_quantity) * (cast(oa.value AS numeric(10,2)))) 
       --When buy/get 
       WHEN (p.get_quantity > 0 or p.get_quantity IS NOT NULL) AND (p.buy_quantity > 0 OR p.buy_quantity IS NOT NULL) AND pgo.object_id = co.object_id     
        THEN ((cast(oa.value AS numeric(10,2)) - COALESCE(pco.discount_amount, 0)) + ((co.quantity - 1) * cast(oa.value AS numeric(10,2)))) 
       WHEN (p.get_quantity = 0 or p.get_quantity IS NULL) AND (p.buy_quantity = 0 OR p.buy_quantity IS NULL) 
        THEN ((cast(oa.value AS numeric(10,2)) - COALESCE(pco.discount_amount, 0)) * co.quantity) 
       ELSE 
        (cast(oa.value AS numeric(10,2)) * co.quantity) 
      END AS "unit_price"  
      FROM cart_object co 
      JOIN object_attr oa ON oa.object_id=co.object_id AND oa.attr_id=50 
      LEFT JOIN promo_cart_objects pco ON pco.cart_id=co.cart_id AND pco.object_id=co.object_id 
      LEFT JOIN promos p ON p.promo_id=pco.promotion_id 
      LEFT JOIN promo_get_objects pgo ON pgo.object_id = co.object_id AND pgo.promo_id = pco.promotion_id 
      LEFT JOIN promo_buy_objects pbo ON pbo.object_id = co.object_id AND pbo.promo_id = pco.promotion_id 
     WHERE co.cart_id=p_cart_id 
     GROUP BY co.cart_id, co.object_id, oa.value, co.quantity, p.get_quantity, p.buy_quantity, pbo.object_id, pgo.object_id, pco.discount_amount, p.promo_id 
    ) AS a; 
    --Get the buyobjects that are in the cart and need to have their line item subtotal recalculated 
    -- :) 
    buy_object_query := 
     'SELECT DISTINCT ON(pbo.object_id) 
      pbo.object_id, p.promo_id, p.buy_quantity, p.get_quantity, pco.discount_amount, co.quantity 
     FROM 
      promo_buy_objects pbo 
     JOIN 
      promos p on p.promo_id = pbo.promo_id AND p.active = TRUE AND now() BETWEEN p.start_date AND p.end_date 
     JOIN 
      promo_cart_objects pco ON pco.object_id = pbo.object_id 
     JOIN 
      cart_object co ON co.cart_id = pco.cart_id AND co.object_id = pbo.object_id 
     WHERE 
      pco.cart_id = ' || p_cart_id || ' 
      AND 
      pbo.object_id IN(SELECT 
         po.object_id 
        FROM 
         promo_objects po 
        JOIN 
         promos p on p.promo_id = po.promotion_id AND p.active = TRUE AND now() BETWEEN p.start_date AND p.end_date 
        JOIN 
         promo_cart_objects pco ON pco.object_id = po.object_id 
        WHERE 
         pco.cart_id = ' || p_cart_id || ' 
        UNION 
        SELECT 
         pgo.object_id 
        FROM 
         promo_get_objects pgo 
        JOIN 
         promos p on p.promo_id = pgo.promo_id AND p.active = TRUE AND now() BETWEEN p.start_date AND p.end_date 
        JOIN 
         promo_cart_objects pco ON pco.object_id = pgo.object_id JOIN cart_object co ON co.cart_id = pco.cart_id 
        WHERE pco.cart_id = ' || p_cart_id || ') 
      AND 
      co.quantity > p.buy_quantity'; 
     FOR buy_object_info IN EXECUTE buy_object_query LOOP 
      --Get the price 
      SELECT cast("value" as numeric(10,2)) INTO buy_object_price FROM object_attr WHERE object_id = buy_object_info.object_id AND attr_id = 50; 
      --What was that original price? Redundant I know ...I might get around to optimizing this function 
      IF (buy_object_info.get_quantity = 0 or buy_object_info.get_quantity IS NULL) AND (buy_object_info.buy_quantity > 0 OR buy_object_info.buy_quantity IS NOT NULL) AND buy_object_info.buy_quantity = buy_object_info.quantity 
       THEN buy_object_orginal_subtotal := ((buy_object_price - COALESCE(buy_object_info.discount_amount, 0)) * buy_object_info.buy_quantity); 
      --When buy only more than the buy quantity in cart 
      ELSIF (buy_object_info.get_quantity = 0 or buy_object_info.get_quantity IS NULL) AND (buy_object_info.buy_quantity > 0 OR buy_object_info.buy_quantity IS NOT NULL) AND buy_object_info.buy_quantity < buy_object_info.quantity 
       THEN buy_object_orginal_subtotal := (((buy_object_price - COALESCE(buy_object_info.discount_amount, 0))) * buy_object_info.buy_quantity) + ((buy_object_info.quantity - buy_object_info.buy_quantity) * (buy_object_price)); 
      --When buy/get 
      ELSIF (buy_object_info.get_quantity > 0 or buy_object_info.get_quantity IS NOT NULL) AND (buy_object_info.buy_quantity > 0 OR buy_object_info.buy_quantity IS NOT NULL)    
       THEN buy_object_orginal_subtotal := ((buy_object_price - COALESCE(buy_object_info.discount_amount, 0)) + ((buy_object_info.quantity - 1) * buy_object_price)); 
      ELSIF (buy_object_info.get_quantity = 0 or buy_object_info.get_quantity IS NULL) AND (buy_object_info.buy_quantity = 0 OR buy_object_info.buy_quantity IS NULL) 
       THEN buy_object_orginal_subtotal := ((buy_object_price - COALESCE(buy_object_info.discount_amount, 0)) * buy_object_info.quantity); 
      ELSE 
       buy_object_orginal_subtotal := (cast(oa.value AS numeric(10,2)) * buy_object_info.quantity); 
      END IF; 
      --Well now we need that other promotion...this is so lame 
      SELECT INTO other_promo_id, other_promo_buy_quantity promo_id, buy_quantity FROM(
        SELECT 
         p.promo_id AS promo_id, p.buy_quantity AS buy_quantity 
        FROM 
         promo_objects po 
        JOIN 
         promos p on p.promo_id = po.promotion_id AND p.active = TRUE AND now() BETWEEN p.start_date AND p.end_date 
        JOIN 
         promo_cart_objects pco ON pco.object_id = po.object_id 
        WHERE 
         pco.cart_id = p_cart_id 
        UNION 
        SELECT 
         p.promo_id AS promo_id, p.buy_quantity AS buy_quantity 
        FROM 
         promo_get_objects pgo 
        JOIN 
         promos p on p.promo_id = pgo.promo_id AND p.active = TRUE AND now() BETWEEN p.start_date AND p.end_date 
        JOIN 
         promo_cart_objects pco ON pco.object_id = pgo.object_id JOIN cart_object co ON co.cart_id = pco.cart_id 
        WHERE pco.cart_id = p_cart_id AND pco.object_id = buy_object_info.object_id) AS foo; 
      --Alrighty now that we have everything we need, let's perform this funky ass math 
      v_subtotal := v_subtotal - buy_object_orginal_subtotal; 
      v_subtotal := v_subtotal + (other_promo_buy_quantity * buy_object_price) + ((buy_object_info.quantity - other_promo_buy_quantity) * (buy_object_price - COALESCE(buy_object_info.discount_amount, 0))); 
     END LOOP; 
    --Get Discount Other 
    --SELECT COALESCE(max(discount_amount), 0), is_shipping_discount INTO v_discount_other FROM cart_promotion WHERE cart_id=p_cart_id; 
    SELECT COALESCE(discount_amount, 0) as discount, COALESCE(is_shipping_discount, false) as is_shipping_discount INTO v_discount_other 
    FROM promo_carts WHERE cart_id=p_cart_id order by discount_amount desc limit 1; 

    -- Determine if shipping is required 
    SELECT count(*) INTO v_items_shipping 
    FROM object o, object_attr oa, cart_object co 
    WHERE oa.object_id = o.object_id AND co.object_id = o.object_id 
    AND attr_id = 74 and cart_id = p_cart_id AND oa.value = 'true'; 

    IF v_items_shipping > 0 THEN 
     v_shipping_required := True; 
    ELSE 
     v_shipping_required := False; 
    END IF; 

    -- Update the cart 
    UPDATE cart SET 
     total_items = COALESCE(v_total_items, 0), 
     subtotal = COALESCE(v_subtotal, 0), 
     is_shipping_required = v_shipping_required, 
     discount_other = COALESCE(v_discount_other.discount, 0), 
     is_shipping_discount = COALESCE(v_discount_other.is_shipping_discount, false) 
    WHERE id = p_cart_id; 

    RETURN QUERY SELECT * from cart WHERE id = p_cart_id; 
    END; 
$BODY$ 
    LANGUAGE 'plpgsql' VOLATILE 
    COST 100 
    ROWS 1000; 
ALTER FUNCTION sp_aggregate_cart(integer) OWNER TO postgres; 
+0

存儲過程在哪裏? – 2010-06-28 13:52:54

+0

是的,我在應用程序代碼的同一個數據庫上運行它,我甚至讓另一個開發人員獲得了我的數據庫副本,並且它們在應用程序中發生了同樣奇怪的錯誤,沒有發生錯誤的原始SQL。 – KacieHouser 2010-06-28 13:53:22

+0

你真的不想看到存儲的程序 – KacieHouser 2010-06-28 13:53:39

回答

1

buy_object_query按順序選擇了錯誤的東西。它會選擇在代碼buy_object_info開頭創建的類型。我是選擇小數整數