2010-06-28 137 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开头创建的类型。我是选择小数整数

相关问题