Hi all. This is the query i need to help with.
OPEN QUERY {&SELF-NAME} FOR EACH shipments NO-LOCK,
FIRST user WHERE user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, user.sysgroup)
AND user.category = 'supplier'
AND (user.address_code = "*" OR user.address_code = shipment.exporter_code) NO-LOCK,
FIRST bf1-user WHERE bf1-user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, bf1-user.sysgroup)
AND bf1-user.category = 'agent'
AND (bf1-user.address_code = "*" OR bf1-user.address_code = shipment.foreign_agent) NO-LOCK,
FIRST bf2-user WHERE porder.bf2-user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, bf2-user.sysgroup)
AND bf2-user.category = 'customer'
AND (bf2-user.address_code = "*" OR porder.bf2-user.address_code = po_shipment.importer_code) NO-LOCK.
Explanation.
bf1-user and bf2-user are buffers for user table.
Indexes for shipments: exporter_code, foreign_agent, importer_code.
Indexes for user: sysuser, sysgroup, category, address-code.
What it should do.
I need to check each shipment record if an user has permission to see it. In user table are stored address-codes for each address category which can be "Customer,Agent or Supplier". It looks like:
user group address category address code
1 a agent a1001
1 a agent a2002
1 a supplier b2001
1 a customer *
If there is an asterix as an address code it means user can see all shipment record for that customer.
Problem. Query speed.
My solution.
Create a list of address codes and work with them them (lookup......) i open query.
DEFINE VARIABLE lv-query AS CHARACTER NO-UNDO.
DEFINE VARIABLE lv-wc AS CHARACTER NO-UNDO.
DEFINE VARIABLE lv-ship-query AS HANDLE NO-UNDO.
CREATE QUERY lv-ship-query.
lv-ship-query:SET-BUFFERS(BUFFER po_shipment:HANDLE).
RUN create-agent-list.
RUN create-supplier-list.
RUN create-customer-list.
IF lv-customer-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.importer_code),'" + lv-customer-list + "',',') NE 0 ".
IF lv-agent-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.foreign_agent),'" + lv-agent-list + "',',') NE 0 ".
IF lv-supplier-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.exporter_code),'" + lv-supplier-list + "',',') NE 0 ".
lv-query = "FOR EACH po_shipment WHERE YES " + lv-wc + " NO-LOCK".
lv-ship-query:QUERY-PREPARE(lv-query).
{&browse-name}:QUERY IN FRAME {&FRAME-NAME} = lv-ship-query.
lv-ship-query:QUERY-OPEN().
What i'm asking for.
I believe there must be better solution how to do this.
Progress version is 9.1D 0980.
THANK YOU for any help / idea.
Peter
P.S. I've never been good in explain things even in my native language so if you have any question please ask. :blush:
P.S2. Users can also search on couple of things so real query is a little bit bigger but it's not relevant:
IF ov_type NE "ALL" THEN lv-wc = lv-wc + "AND" + " po_shipment.ship_type = '" + ov_type + "'".
IF ov_ref-no NE 0 THEN lv-wc = lv-wc + "AND" + " po_shipment.ship_id = '" + STRING(ov_ref-no) + "'".
IF cb_jobs NE "ALL" THEN lv-wc = lv-wc + "AND ((" + cb_jobs + " = 'YES' AND po_shipment.mfrt_jobdisp NE '') OR (" + cb_jobs + " = 'NO' AND po_shipment.mfrt_jobdisp = ''))".
IF ov_agent NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.foreign_agent = '" + ov_agent + "'".
IF ov_agent-ref NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.agent_ref = '" + ov_agent-ref + "'".
IF ov_vessel NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.vessel_flno = '" + ov_vessel + "'".
IF ov_carrier NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.carrier_code = '" + ov_carrier + "'".
IF ov_importer NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.importer_code = '" + ov_importer + "'".
IF ov_exporter NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.exporter_code = '" + ov_exporter + "'".
IF ov_obill-mawb NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.ocean_mawb = '" + ov_obill-mawb + "'".
IF ov_hbill-hawb NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.house_hawb = '" + ov_hbill-hawb + "'".
IF ov_etaf NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.eta >= '" + STRING(ov_etaf) + "'".
IF ov_etat NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.eta <= '" + STRING(ov_etat) + "'".
IF ov_etsf NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.ets >= '" + STRING(ov_etsf) + "'".
IF ov_etst NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.ets <= '" + STRING(ov_etst) + "'".
OPEN QUERY {&SELF-NAME} FOR EACH shipments NO-LOCK,
FIRST user WHERE user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, user.sysgroup)
AND user.category = 'supplier'
AND (user.address_code = "*" OR user.address_code = shipment.exporter_code) NO-LOCK,
FIRST bf1-user WHERE bf1-user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, bf1-user.sysgroup)
AND bf1-user.category = 'agent'
AND (bf1-user.address_code = "*" OR bf1-user.address_code = shipment.foreign_agent) NO-LOCK,
FIRST bf2-user WHERE porder.bf2-user.sysuser = gv-sysuser
AND CAN-DO (gv-sysgroup, bf2-user.sysgroup)
AND bf2-user.category = 'customer'
AND (bf2-user.address_code = "*" OR porder.bf2-user.address_code = po_shipment.importer_code) NO-LOCK.
Explanation.
bf1-user and bf2-user are buffers for user table.
Indexes for shipments: exporter_code, foreign_agent, importer_code.
Indexes for user: sysuser, sysgroup, category, address-code.
What it should do.
I need to check each shipment record if an user has permission to see it. In user table are stored address-codes for each address category which can be "Customer,Agent or Supplier". It looks like:
user group address category address code
1 a agent a1001
1 a agent a2002
1 a supplier b2001
1 a customer *
If there is an asterix as an address code it means user can see all shipment record for that customer.
Problem. Query speed.
My solution.
Create a list of address codes and work with them them (lookup......) i open query.
DEFINE VARIABLE lv-query AS CHARACTER NO-UNDO.
DEFINE VARIABLE lv-wc AS CHARACTER NO-UNDO.
DEFINE VARIABLE lv-ship-query AS HANDLE NO-UNDO.
CREATE QUERY lv-ship-query.
lv-ship-query:SET-BUFFERS(BUFFER po_shipment:HANDLE).
RUN create-agent-list.
RUN create-supplier-list.
RUN create-customer-list.
IF lv-customer-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.importer_code),'" + lv-customer-list + "',',') NE 0 ".
IF lv-agent-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.foreign_agent),'" + lv-agent-list + "',',') NE 0 ".
IF lv-supplier-list NE "" THEN lv-wc = lv-wc + "AND" + " LOOKUP(STRING(po_shipment.exporter_code),'" + lv-supplier-list + "',',') NE 0 ".
lv-query = "FOR EACH po_shipment WHERE YES " + lv-wc + " NO-LOCK".
lv-ship-query:QUERY-PREPARE(lv-query).
{&browse-name}:QUERY IN FRAME {&FRAME-NAME} = lv-ship-query.
lv-ship-query:QUERY-OPEN().
What i'm asking for.
I believe there must be better solution how to do this.
Progress version is 9.1D 0980.
THANK YOU for any help / idea.
Peter
P.S. I've never been good in explain things even in my native language so if you have any question please ask. :blush:
P.S2. Users can also search on couple of things so real query is a little bit bigger but it's not relevant:
IF ov_type NE "ALL" THEN lv-wc = lv-wc + "AND" + " po_shipment.ship_type = '" + ov_type + "'".
IF ov_ref-no NE 0 THEN lv-wc = lv-wc + "AND" + " po_shipment.ship_id = '" + STRING(ov_ref-no) + "'".
IF cb_jobs NE "ALL" THEN lv-wc = lv-wc + "AND ((" + cb_jobs + " = 'YES' AND po_shipment.mfrt_jobdisp NE '') OR (" + cb_jobs + " = 'NO' AND po_shipment.mfrt_jobdisp = ''))".
IF ov_agent NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.foreign_agent = '" + ov_agent + "'".
IF ov_agent-ref NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.agent_ref = '" + ov_agent-ref + "'".
IF ov_vessel NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.vessel_flno = '" + ov_vessel + "'".
IF ov_carrier NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.carrier_code = '" + ov_carrier + "'".
IF ov_importer NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.importer_code = '" + ov_importer + "'".
IF ov_exporter NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.exporter_code = '" + ov_exporter + "'".
IF ov_obill-mawb NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.ocean_mawb = '" + ov_obill-mawb + "'".
IF ov_hbill-hawb NE "" THEN lv-wc = lv-wc + "AND" + " po_shipment.house_hawb = '" + ov_hbill-hawb + "'".
IF ov_etaf NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.eta >= '" + STRING(ov_etaf) + "'".
IF ov_etat NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.eta <= '" + STRING(ov_etat) + "'".
IF ov_etsf NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.ets >= '" + STRING(ov_etsf) + "'".
IF ov_etst NE ? THEN lv-wc = lv-wc + "AND" + " po_shipment.ets <= '" + STRING(ov_etst) + "'".