Virtuemart cart string structure in database - joomla1.5

I'm using the Joomla's extension Virtuemart 1.1.9 with joomla 1.5 to create my shopping cart. With the help of another component, I can upload a plain text file to the server with the Product Id and the quantity. With the following routine I can conolidate the load into the cart.
The problem with this method is that when I proceed to place the order, the products prices don't multiply with the quantity ordered to obtain the total of the order.
Any ideas?
here is the code
DECLARE done INT DEFAULT 0;
declare producto, cantidad, cliente, carga, categoria int;
declare cantidadreg, cuenta, i int default 0;
declare cadena text default "";
declare varcarga int default 0;
declare cur1 cursor for select jos_vm_product.product_id, cant_producto, id_cliente, datos_cargas_vm.id_carga, category_id
from datos_cargas_vm inner join cargas_vm on datos_cargas_vm.id_carga=cargas_vm.id_carga
inner join jos_vm_product on datos_cargas_vm.id_producto=jos_vm_product.product_sku
inner join jos_vm_product_category_xref on jos_vm_product.product_id = jos_vm_product_category_xref.product_id
where estado_carga='P'
order by datos_cargas_vm.id_carga, jos_vm_product.product_id;
declare continue handler for not found set done = true;
open cur1;
read_loop: LOOP
fetch cur1 into producto, cantidad, cliente, carga, categoria;
if done then
leave read_loop;
end if;
if varcarga!=carga then
select count(*) into cantidadreg from datos_cargas_vm inner join cargas_vm on datos_cargas_vm.id_carga=cargas_vm.id_carga
inner join jos_vm_product on datos_cargas_vm.id_producto=jos_vm_product.product_sku
inner join jos_vm_product_category_xref on jos_vm_product.product_id = jos_vm_product_category_xref.product_id
where estado_carga='P' and datos_cargas_vm.id_carga=carga;
set varcarga:=carga;
set cadena:=concat("a:",cast(cantidadreg+1 as char),":{s:3:\"idx\";i:",cast(cantidadreg as char),";");
set i:=0;
end if;
set cadena:=concat(cadena,"i:",cast(i as char),";a:5:{s:8:\"quantity\";i:",cast(cantidad as char),
";s:10:\"product_id\";s:5:\"",cast(producto as char),"\";s:9:\"parent_id\";i:",cast(producto as char),
";s:11:\"category_id\";i:",cast(categoria as char),";s:11:\"description\";s:0:\"\";}");
set i:=i+1;
if i=cantidadreg then
set cadena:=concat(cadena,"}");
-- select cantidadreg,cadena;
select count(*) into cantidadreg from jos_vm_cart where user_id = cliente;
if cantidadreg=0 then
insert into jos_vm_cart(user_id,cart_content) values(cliente,cadena);
else
update jos_vm_cart set cart_content=cadena where user_id=cliente;
end if;
update cargas_vm set estado_carga='C' where id_carga=carga;
end if;
END LOOP;
close cur1;

If you're going to bypass all the virtuemart logic to load the cart, you're likely going to have to emulate it and do the math at the same time as the load.

Related

Update table every 1000 rows

I am trying to do an update on a specific record every 1000 rows using Postgres. I am looking for a better way to do that. My function is described below:
CREATE OR REPLACE FUNCTION update_row()
RETURNS void AS
$BODY$
declare
myUID integer;
nRow integer;
maxUid integer;
BEGIN
nRow:=1000;
select max(uid_atm_inp) from tab into maxUid where field1 = '1240200';
loop
if (nRow > 1000 and nRow < maxUid) then
select uid from tab into myUID where field1 = '1240200' and uid >= nRow limit 1;
update tab
set field = 'xxx'
where field1 = '1240200' and uid = myUID;
nRow:=nRow+1000;
end if;
end loop;
END; $BODY$
LANGUAGE plpgsql VOLATILE
How can I improve this procedure? I think there is something wrong. The loop does not end and takes too much time.
To perform this task in SQL, you could use the row_number window function and update only those rows where the number is divisible by 1000.
Your loop doesn't finish because there is no EXIT or RETURN in it.
I doubt you could ever rival the performance of a standard SQL update with a procedural loop. Instead of doing it a row at a time, just do it all as a single statement:
with t2 as (
select
uid, row_number() over (order by 1) as rn
from tab
where field1 = '1240200'
)
update tab t1
set field = 'xxx'
from t2
where
t1.uid = t2.uid and
mod (t2.rn, 1000) = 0
Per my comment, I am presupposing what you mean by "every 1000th row," as without some designation of how to determine what tuple is what row number. That is easily edited by changing the "order by" criteria.
Adding a second where clause on the update (t1.field1 = '1240200') can't hurt but might not be necessary if these are nested loop.
This might be notionally similar to what Laurenz has in mind.
I solved this way:
declare
myUID integer;
nRow integer;
rowNum integer;
checkrow integer;
myString varchar(272);
cur_check_row cursor for select uid , row_number() over (order by 1) as rn, substr(fieldxx,1,244)
from table where field1 = '1240200' and uid >= 1000 ORDER BY uid;
BEGIN
open cur_check_row;
loop
fetch cur_check_row into myUID, rowNum, myString;
EXIT WHEN NOT FOUND;
select mod(rowNum, 1000) into checkrow;
if checkrow = 0 then
update table
set fieldxx= myString||'O'
where uid in (myUID);
end if;
end loop;
close cur_check_row;

How to use INTO to assign select result from query inside postgres function

In postgres I made this function, and when it's called, it prints the count value, not the c.first_name value that I passed into variable. I don't know if this is the correct way to do this. How can I correct this?
declare
mostExperienced text;
BEGIN
SELECT COUNT(*) AS count, c.first_name INTO mostExperienced
FROM crew_members c
INNER JOIN aircrafts_members am ON am.crew_id = c.id
GROUP BY am.crew_id, c.first_name ORDER BY count DESC LIMIT 1;
RETURN mostExperienced;
END;
There are two variables in that SELECT ... INTO, so a record would probably be a better choice
declare
mostExperienced RECORD;
BEGIN
SELECT COUNT(*) AS count, c.first_name
INTO mostExperienced
FROM crew_members c
INNER JOIN aircrafts_members am ON am.crew_id = c.id
GROUP BY am.crew_id, c.first_name ORDER BY count DESC
LIMIT 1;
RETURN mostExperienced.first_name;
END;

Recursive with cursor on psql, nothing data found

How to use a recursive query and then using cursor to update multiple rows in postgresql. I try to return data but no data is found. Any alternative to using recursive query and cursor, or maybe better code please help me.
drop function proses_stock_invoice(varchar, varchar, character varying);
create or replace function proses_stock_invoice
(p_medical_cd varchar,p_post_cd varchar, p_pstruserid character varying)
returns void
language plpgsql
as $function$
declare
cursor_data refcursor;
cursor_proses refcursor;
v_medicalCd varchar(20);
v_itemCd varchar(20);
v_quantity numeric(10);
begin
open cursor_data for
with recursive hasil(idnya, level, pasien_cd, id_root) as (
select medical_cd, 1, pasien_cd, medical_root_cd
from trx_medical
where medical_cd = p_pstruserid
union all
select A.medical_cd, level + 1, A.pasien_cd, A.medical_root_cd
from trx_medical A, hasil B
where A.medical_root_cd = B.idnya
)
select idnya from hasil where level >=1;
fetch next from cursor_data into v_medicalCd;
return v_medicalCd;
while (found)
loop
open cursor_proses for
select B.item_cd, B.quantity from trx_medical_resep A
join trx_resep_data B on A.medical_resep_seqno = B.medical_resep_seqno
where A.medical_cd = v_medicalCd and B.resep_tp = 'RESEP_TP_1';
fetch next from cursor_proses into v_itemCd, v_quantity;
while (found)
loop
update inv_pos_item
set quantity = quantity - v_quantity, modi_id = p_pstruserid, modi_id = now()
where item_cd = v_itemCd and pos_cd = p_post_cd;
end loop;
close cursor_proses;
end loop;
close cursor_data;
end
$function$;
but nothing data found?
You have a function with return void so it will never return any data to you. Still you have the statement return v_medicalCd after fetching the first record from the first cursor, so the function will return from that point and never reach the lines below.
When analyzing your function you have (1) a cursor that yields a number of idnya values from table trx_medical, which is input for (2) a cursor that yields a number of v_itemCd, v_quantity from tables trx_medical_resep, trx_resep_data for each idnya, which is then used to (3) update some rows in table inv_pos_item. You do not need cursors to do that and it is, in fact, extremely inefficient. Instead, turn the whole thing into a single update statement.
I am assuming here that you want to update an inventory of medicines by subtracting the medicines prescribed to patients from the stock in the inventory. This means that you will have to sum up prescribed amounts by type of medicine. That should look like this (note the comments):
CREATE FUNCTION proses_stock_invoice
-- VVV parameter not used
(p_medical_cd varchar, p_post_cd varchar, p_pstruserid varchar)
RETURNS void AS $function$
UPDATE inv_pos_item -- VVV column repeated VVV
SET quantity = quantity - prescribed.quantity, modi_id = p_pstruserid, modi_id = now()
FROM (
WITH RECURSIVE hasil(idnya, level, pasien_cd, id_root) AS (
SELECT medical_cd, 1, pasien_cd, medical_root_cd
FROM trx_medical
WHERE medical_cd = p_pstruserid
UNION ALL
SELECT A.medical_cd, level + 1, A.pasien_cd, A.medical_root_cd
FROM trx_medical A, hasil B
WHERE A.medical_root_cd = B.idnya
)
SELECT B.item_cd, sum(B.quantity) AS quantity
FROM trx_medical_resep A
JOIN trx_resep_data B USING (medical_resep_seqno)
JOIN hasil ON A.medical_cd = hasil.idnya
WHERE B.resep_tp = 'RESEP_TP_1'
--AND hacil.level >= 1 Useless because level is always >= 1
GROUP BY 1
) prescribed
WHERE item_cd = prescribed.item_cd
AND pos_cd = p_post_cd;
$function$ LANGUAGE sql STRICT;
Important
As with all UPDATE statements, test this code before you run the function. You can do that by running the prescribed sub-query separately as a stand-alone query to ensure that it does the right thing.

Using a for loop and if statement in postgres

How come this is not working? Basically, this proc will update columns in the main buyer table to check if the user has data in other tables.
DO language plpgsql $$
DECLARE
buyer integer;
BEGIN
FOR buyer IN SELECT id FROM buyers
LOOP
IF (SELECT count(*) FROM invoice WHERE buyer_id = buyer) > 0 THEN
UPDATE buyers SET has_invoice = true WHERE id = buyer;
ELSE
UPDATE buyers SET has_invoice = false WHERE id = buyer;
END IF;
END LOOP;
RETURN;
END;
$$;
It is unclear what is "not working". Either way, use this equivalent UPDATE statement instead:
UPDATE buyers b
SET has_invoice = EXISTS (SELECT 1 id FROM invoice WHERE buyer_id = b.id);
If you don't need redundant storage for performance, you can use a VIEW or generated column for the same purpose. Then the column has_invoice is calculated on the fly and always up to date. Instructions in this closely related answer:
Store common query as column?

TSQL Cursor Infinite Loop without TOP xxx in SELECT Statement

I have a curious problem with an infinite loop in a TSQL cursor. The cursor loops infinitely when I do not add TOP 300 to the defining select statement of the cursor. The following is an example of the code: Any assistance to this issue is much appreciated.
DECLARE #Done BIT
SET #Done = 0
DECLARE cursOut CURSOR LOCAL FAST_FORWARD
FOR
SELECT
--TOP 300
FirstName FirstName
,LastName LastName
,MiddleName MiddleName
,Email Email
,Address1 Address1
,Address2 Address2
,City City
,[State] [State]
FROM StagedUsers
OPEN cursOut;
WHILE (#Done = 0)
BEGIN
--Fetch next row
FETCH NEXT
FROM cursOut
INTO ,#v_FirstName
,#v_LastName
,#v_MiddleName
,#v_Email
,#v_Address1
,#v_Address2
,#v_City
,#v_State
IF (##FETCH_STATUS <> 0)
BEGIN
SET #Done = 1
BREAK
END
--if #batch = 0
BEGIN TRANSACTION
--process statements
--updates or insert statements
--Commit transaction
COMMIT TRANSACTION
--End While
END
--CleanUp:
CLOSE cursOut
DEALLOCATE cursOut
Thanks,
Renegrin
First I think you do not need transaction here, I presume it is only one statement executed, so remove transaction from code.
Second do it without #done flag, it is confusing (it is probably not problem here).
DECLARE #v_FirstName VARCHAR(500),#v_LastName VARCHAR(500),#v_MiddleName VARCHAR(500),#v_Email VARCHAR(500),#v_Address1 VARCHAR(500),#v_Address2 VARCHAR(500),#v_City VARCHAR(500),#v_State VARCHAR(500)
DECLARE cursOut CURSOR FAST_FORWARD FOR
SELECT FirstName FirstName,LastName LastName,MiddleName MiddleName,Email Email,Address1 Address1,Address2 Address2,City City,[State] [State]
FROM StagedUsers
OPEN cursOut;
FETCH NEXT FROM cursOut INTO #v_FirstName,#v_LastName,#v_MiddleName,#v_Email,#v_Address1,#v_Address2,#v_City,#v_State
declare #i int = 1
WHILE ##FETCH_STATUS = 0
BEGIN
print cast(#i as varchar(10))
--> statement here
FETCH NEXT FROM cursOut INTO #v_FirstName,#v_LastName,#v_MiddleName,#v_Email,#v_Address1,#v_Address2,#v_City,#v_State
set #i = #i + 1
END
CLOSE cursOut
DEALLOCATE cursOut
Do you want to update current row where cursor point? If so, there is way to do it.
Is there any indexes on table? Can you post an update query?