DBMS_ASSERT.enquote_name() in Oracle - sql

I have a sample code from http://phil-sqltips.blogspot.com/2015/07/beware-of-empty-partitions.html and I'd like to understand this xmlgen sql.
WITH t AS (
SELECT table_owner
, table_name
, partition_name
, TO_NUMBER (EXTRACTVALUE (XMLTYPE (DBMS_XMLGEN.getxml ('SELECT COUNT(*) AS rows_exist FROM '
|| DBMS_ASSERT.enquote_name (str => table_owner)
|| '.'
|| DBMS_ASSERT.enquote_name (str => table_name)
|| ' PARTITION ('
|| DBMS_ASSERT.enquote_name (str => partition_name)
|| ') WHERE ROWNUM <= 1'
)
)
, '/ROWSET/ROW/ROWS_EXIST'
)
) AS rows_exist
FROM all_tab_partitions
WHERE table_owner = 'WH'
AND table_name IN ('POINT_OF_SALE_FACTS')
ORDER BY table_owner
, table_name
, partition_position
)
SELECT 'ALTER TABLE '
|| DBMS_ASSERT.enquote_name (str => table_owner)
|| '.'
|| DBMS_ASSERT.enquote_name (str => table_name)
|| ' DROP PARTITION '
|| DBMS_ASSERT.enquote_name (str => partition_name)
|| ';' AS stmt
, t.*
FROM t
WHERE rows_exist = 0
;
I've found most of them except this,
DBMS_ASSERT.enquote_name (str => table_owner).
What is the syntax of arrow in (str => table_owner) inside of enquote_name?
I found this https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_assert.htm#BABDEHBC but there is no such arrow syntax, and couldn't find web sites for this syntax.

That's the named parameter syntax. Here's the relevant documentation. So str => table_name says to set the str parameter to table_name.
In this case, it isn't necessary, since str is the first parameter for DBMS_ASSERT.ENQUOTE_NAME. So you could omit it and just call DBMS_ASSERT.enquote_name(table_owner).
But in some cases it can be very useful. For example, when there are multiple optional parameters (with defaults) and you only want to specify one of them. Or when you want to clarify the purpose of a parameter by displaying the parameter name next to the value.

Related

How to reference function in Node.js Postgres API Call

I have this function called pvt():
Create Or Replace Function pvt()
RETURNS void
LANGUAGE 'plpgsql'
AS '
declare
sqlColumn varchar;
qr varchar;
columnlist varchar;
Begin
sqlColumn= ''select distinct D.sys_cat from (select Row_Number() Over (Partition By Project,Date_ Order By System_) as sys_cat From your_table) D order by D.sys_cat;'';
qr=''prepare pvtstmt as Select D.Project,D.Date_,'';
For columnlist In EXECUTE sqlColumn
Loop
qr=qr || ''
Max(Case When sys_cat=''|| chr(39) || columnlist || chr(39) ||'' Then System_ ||'' ||chr(39)||''-''||chr(39)||''|| Result_ Else '' ||chr(39)||chr(39)||'' End) As System'' || columnlist || '' , '';
END LOOP;
qr=substr(qr, 0, length(qr) - 1);
qr=qr || ''From
(select *, Row_Number() Over (Partition By Project,Date_ Order By System_) as sys_cat From your_table) D Where D.Project='' || chr(39) || ''Proj1'' || chr(39) || ''Group By D.Project,D.Date_ Order By D.Project,D.Date_'';
Deallocate All;
EXECUTE qr;
End;
'
I need to execute these SQL statements:
Select pvt();
Execute pvtstmt;
Currently, I have a queries.js file where I have defined:
const getRunsByProjectTable = `
Select pvt();
Execute pvtstmt;
`
However, when I try to make the API call I do not receive any data back:
const getRunsByProjectTable = (req, res) => {
pool.query(queries.getRunsByProjectTable, (error, results) => {
if (error) throw error;
res.status(200).json(results.rows);
})
}
Does anyone know what the issue may be? Any help would be much appreciated!

XMLTable query returns no result

I'm only passingly familiar with XML. I need to parse a response from a SOAP request. From a lot of searching, I've developed the following query to try to extract the status. Ultimately, I'd like to get the status, cntr and cntr_status fields from the response. My query gives no error, but also no results. What noob error am I making?
SELECT *
FROM XMLTABLE (
XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
'http://service.xxx.com/' AS "xxx"),
'/soapenv:Envelope/soapenv:Body/xxx:sendDataResponse/xxx:sendDataReturn/xxx:result'
PASSING XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>' ||
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
' <soapenv:Body>' ||
' <sendDataResponse xmlns="http://service.xxx.com">' ||
' <sendDataReturn>' ||
' <result>' ||
' <build>Build 1</build>' ||
' <status>SUCCESS</status>' ||
' <cntr_statuses>' ||
' <cntr_result>' ||
' <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
' </cntr_result>' ||
' <cntr_result>' ||
' <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
' </cntr_result>' ||
' </cntr_statuses>' ||
' </result>' ||
' </sendDataReturn>' ||
' </sendDataResponse>' ||
' </soapenv:Body>' ||
'</soapenv:Envelope>')
COLUMNS status VARCHAR2(20) PATH 'xxx:status') xmlstuff ;
A sample response from the service is hard-coded into the XMLTYPE function.
I've tried any number of query strings and column paths involving the xxx namespace, all yielding no results.
There could be hundreds of cntr and cntr_status pairs.
Thanks for looking!
Using the DEFAULT namespace (since you don't define a prefix for http://service.xxx.com) and removing the references to xxx: appears to work:
SELECT *
FROM XMLTABLE (
XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
DEFAULT 'http://service.xxx.com'
),
'/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
PASSING XMLTYPE(
'<?xml version="1.0" encoding="UTF-8"?>' ||
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
' <soapenv:Body>' ||
' <sendDataResponse xmlns="http://service.xxx.com">' ||
' <sendDataReturn>' ||
' <result>' ||
' <build>Build 1</build>' ||
' <status>SUCCESS</status>' ||
' <cntr_statuses>' ||
' <cntr_result>' ||
' <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
' <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
' </cntr_result>' ||
' </cntr_statuses>' ||
' </result>' ||
' </sendDataReturn>' ||
' </sendDataResponse>' ||
' </soapenv:Body>' ||
'</soapenv:Envelope>'
)
sqlfiddle here
Then to get the first cntr and cntr_status:
SELECT *
FROM XMLTABLE (
XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
DEFAULT 'http://service.xxx.com'
),
'/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
PASSING XMLTYPE(
'<?xml version="1.0" encoding="UTF-8"?>' ||
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
' <soapenv:Body>' ||
' <sendDataResponse xmlns="http://service.xxx.com">' ||
' <sendDataReturn>' ||
' <result>' ||
' <build>Build 1</build>' ||
' <status>SUCCESS</status>' ||
' <cntr_statuses>' ||
' <cntr_result>' ||
' <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
' <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
' </cntr_result>' ||
' </cntr_statuses>' ||
' </result>' ||
' </sendDataReturn>' ||
' </sendDataResponse>' ||
' </soapenv:Body>' ||
'</soapenv:Envelope>'
)
COLUMNS
status VARCHAR2(20) PATH 'status',
cntr VARCHAR2(20) PATH 'cntr_statuses/cntr_result/cntr[1]',
cntr_status VARCHAR2(20) PATH 'cntr_statuses/cntr_result/cntr_status[1]'
) xmlstuff;
sqlfiddle here
Update for revised XML format
Ideally, you should be able to use the XPATH '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result/cntr_status/cntr_result' in the XMLTABLE and then get the status with the path ./../../status; however, I keep getting null values when trying to traverse to a parent element and couldn't find a working solution.
SELECT x.*
FROM table_name t
CROSS JOIN
XMLTABLE(
XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
DEFAULT 'http://service.xxx.com'
),
'/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result/cntr_statuses/cntr_result'
PASSING XMLTYPE(t.xml)
COLUMNS
status VARCHAR2(20) PATH './../../status',
cntr VARCHAR2(20) PATH 'cntr',
cntr_status VARCHAR2(20) PATH 'cntr_status'
) x;
sqlfiddle here
According to this comment, it will work in Oracle 11.2.0.4 but if you try it in Oracle 11.2.0.2 then status will be NULL (which is the result seen on SQLFiddle).
Instead, with multiple cntr_result elements you can use two XMLTABLE:
SELECT x.status,
c.cntr,
c.cntr_status
FROM table_name t
CROSS JOIN
XMLTABLE(
XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
DEFAULT 'http://service.xxx.com'
),
'/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
PASSING XMLTYPE(t.xml)
COLUMNS
status VARCHAR2(20) PATH 'status',
cntr_statuses XMLTYPE PATH 'cntr_statuses'
) x
CROSS JOIN
XMLTABLE(
XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
DEFAULT 'http://service.xxx.com'
),
'/cntr_statuses/cntr_result'
PASSING x.cntr_statuses
COLUMNS
cntr VARCHAR2(20) PATH 'cntr',
cntr_status VARCHAR2(20) PATH 'cntr_status'
) c;
Assuming your data is in the xml column of the table_name table.
Then the output is:
STATUS
CNTR
CNTR_STATUS
SUCCESS
1234567890A
SUCCESS
SUCCESS
1234567890B
SUCCESS
sqlfiddle here

Oracle Apex Refreshing Chart is not working

I have created a dialog page in my apex application. On this page a user is possible to select several filters for a chart. After clicking on a button the user is redirected to the previous page and the region which contains the chart is refreshed. The problem I have is that setting the filters doesn't work. After being redirected to the previous page the chart is being refreshed endless until an error occurs that says: Bad Gateway. So I don't see any result of the chart. Is it possible that the query of my chart is too complex? The dialog page contains four items of type shuttle and here is the query of my chart.
select COUNT(TRIGGER_TABLE.DATUM_UHRZEIT) as Anzahl_Trigger,
TEST.ID as ID
from BRIDGE_SYSTEM_TRIGGER, SYSTEM_TABLE, TRIGGER_TABLE, FAHRT, TEST, MITARBEITER
where BRIDGE_SYSTEM_TRIGGER.SYSTEM_TABLE_SYSTEM_ID = SYSTEM_TABLE.SYSTEM_ID
and BRIDGE_SYSTEM_TRIGGER.TRIGGER_TABLE_TRIGGER_ID = TRIGGER_TABLE.TRIGGER_ID
and TRIGGER_TABLE.FAHRT_FAHRT_ID = FAHRT.FAHRT_ID
and MITARBEITER.QNUMMER = FAHRT.MITARBEITER_QNUMMER
and FAHRT.TEST_ID = TEST_ID
and TRIGGER_TABLE.PRIORITAET = 0
or ((instr(':' || upper(:P26_Tests) || ':', upper(Test.Test_ID)) > 0)
or (instr(':' || upper(:P26_UEBERSYSTEM) || ':',':' || upper(system_table.system_name) ||':') > 0) or (instr(':' || upper(:P26_UNTERSYSTEM) || ':',':' || upper(system_table.system_name) ||':') > 0)
or (instr(':' || upper(:P26_COUNTRIES) || ':', upper(FAHRT.LAND)) > 0)
or (instr(':' || upper(:P26_REF) || ':', upper(Test.REF)) > 0)
or (instr(':' || upper(:P26_DRIVER) || ':', upper(MITARBEITER.QNUMMER)) > 0))
GROUP BY TEST.ID
ORDER BY TEST_ID;
The query doesn't throw any errors. Another problem I thought about is that something with the refresh is not correctly defined or not working.
I could solve my problem! There was no mistake in the refresh. Although I could not proove why the refresh was not loading, I think it was a runtime-issue because the query was too complex.
I changed the last five or-conditions of my query to and-clauses. After doing that the refresh works again.
select COUNT(TRIGGER_TABLE.DATUM_UHRZEIT) as Anzahl_Trigger,
TEST.ID as ID
from BRIDGE_SYSTEM_TRIGGER, SYSTEM_TABLE, TRIGGER_TABLE, FAHRT, TEST, MITARBEITER
where BRIDGE_SYSTEM_TRIGGER.SYSTEM_TABLE_SYSTEM_ID = SYSTEM_TABLE.SYSTEM_ID
and BRIDGE_SYSTEM_TRIGGER.TRIGGER_TABLE_TRIGGER_ID = TRIGGER_TABLE.TRIGGER_ID
and TRIGGER_TABLE.FAHRT_FAHRT_ID = FAHRT.FAHRT_ID
and MITARBEITER.QNUMMER = FAHRT.MITARBEITER_QNUMMER
and FAHRT.TEST_ID = TEST_ID
and TRIGGER_TABLE.PRIORITAET = 0
and ((instr(':' || upper(:P26_Tests) || ':', upper(Test.Test_ID)) > 0)
and (instr(':' || upper(:P26_UEBERSYSTEM) || ':',':' || upper(system_table.system_name) ||':') > 0) or (instr(':' || upper(:P26_UNTERSYSTEM) || ':',':' || upper(system_table.system_name) ||':') > 0)
and (instr(':' || upper(:P26_COUNTRIES) || ':', upper(FAHRT.LAND)) > 0)
and (instr(':' || upper(:P26_REF) || ':', upper(Test.REF)) > 0)
and (instr(':' || upper(:P26_DRIVER) || ':', upper(MITARBEITER.QNUMMER)) > 0))
GROUP BY TEST.ID
ORDER BY TEST_ID;
The query has definetely to look like that because I want to filter and that's why I need the and-condition. Each element has to be true, otherwise wrong results will appear.

Build PostgreSQL SELECT dynamically with different number of parameters

I'd like to write my PostgreSQL (9.3) SELECT dynamically based on the user's fields filled out in the query form:
$cond = '';
if ($_REQUEST['sel_when_a'] != '')
$cond .= ' AND field_lastmod >= $2';
if ($_REQUEST['sel_when_b'] != '')
$cond .= ' AND field_lastmod <= $3';
$sel = ExecSQLP('SELECT field_value, field_lastmod
FROM my_values
WHERE field_value ILIKE \'%\' || $1 || \'%\'
. $cond .
' ORDER BY node_id;'
, array( $_REQUEST['sel_find'], $_REQUEST['sel_when_a'], $_REQUEST['sel_when_b'] ));
(ExecSQLP is my function to execute an SQL statement with the arguments, based on pg_query_params.)
This is simple and elegant, but I get an error message: Query failed: ERROR: bind message supplies 3 parameters, but prepared statement "" requires 1 if sel_when_a ("after") and sel_when_b ("before") are empty.
I think this shouldn't be an error in PostgreSQL as it doesn't do any bad if an unused parameter is supplied. Can I suppress this error? Othervise how to build the statement with different number of parameters? I have a lot of them, not only the 3 above. It'd be terrible to prepare for the several cases with renumbered parameters if PostgreSQL doesn't allow this.
The documentation: http://www.postgresql.org/docs/9.3/interactive/sql-expressions.html#SQL-EXPRESSIONS-PARAMETERS-POSITIONAL is not very useful for this case.
Thanks for your tips. SQL injection vulnerability is not accepted!
(Perhaps similar to How to handle dynamic number of parameters in querystring when building REST api?, but the relation is not always "equals to a string".)
I'd build the parameter array while building query. Like this:
$cond = '';
$params = array( $_REQUEST['sel_find'] );
if ($_REQUEST['sel_when_a'] != '') {
$params[] = $_REQUEST['sel_when_a'];
$cond .= ' AND field_lastmod >= $'.count($params);
}
if ($_REQUEST['sel_when_b'] != '') {
$params[] = $_REQUEST['sel_when_b'];
$cond .= ' AND field_lastmod <= $'.count($params);
}
$sel = ExecSQLP('SELECT field_value, field_lastmod
FROM my_values
WHERE field_value ILIKE \'%\' || $1 || \'%\''
. $cond .
' ORDER BY node_id;'
, $params ));
It's not very sensible to ignore wrong number or parameters - in 99% of cases it would be a programming error.
If you would've used PDO for database connection you could use named parameters like this:
$cond = '';
$params = array( ':sel_find' => $_REQUEST['sel_find'] );
if ($_REQUEST['sel_when_a'] != '') {
$cond .= ' AND field_lastmod >= :sel_when_a';
$params[':sel_when_a'] = $_REQUEST['sel_when_a'];
}
if ($_REQUEST['sel_when_b'] != '') {
$cond .= ' AND field_lastmod <= :sel_when_b';
$params[':sel_when_b'] = $_REQUEST['sel_when_b'];
}
$sel = $dbh->prepare('SELECT field_value, field_lastmod
FROM my_values
WHERE field_value ILIKE \'%\' || :sel_find || \'%\''
. $cond .
' ORDER BY node_id;')->execute($params);

owa_util.mime_header Issue - Trying to extract a Excel File from a query

'm having a problem with my one procedure that suppose to generate an Excel file, the procedure is this one:
CREATE OR REPLACE PROCEDURE GENERATE_REPORT_P(P_CONTRACT_NUM IN VARCHAR2 DEFAULT NULL,
P_CUSTOMER_NAME IN VARCHAR2 DEFAULT NULL,
P_CUSTOMER_NUM IN VARCHAR2 DEFAULT NULL,
P_UPDATE_DATE_START IN DATE DEFAULT NULL,
P_UPDATE_DATE_END IN DATE DEFAULT NULL,
P_ORDER_NUM IN VARCHAR2 DEFAULT NULL) IS
vRecords BOOLEAN := FALSE;
BEGIN
FOR i IN (SELECT
a.contract_num,
d.customer_abt_number,
d.customer_name,
c.doms_order_num order_num,
e.service_tag asset,
e.sku,
e.field,
e.previous_value,
e.new_value,
e.update_date, --to_char(i.update_date, 'DD-MON-RRRR HH12:MI:SS')
e.updated_by
FROM contracts a,
order_extension b,
orders c,
customers d,
abt_cisi_log e
WHERE a.id = b.contract_id
AND c.id = b.order_id
AND d.id = a.customer_id
AND c.id = e.order_id
--parameters
AND a.contract_num LIKE NVL(p_contract_num, a.contract_num)
AND d.customer_abt_number LIKE
NVL(p_customer_num, d.customer_abt_number)
AND d.customer_name LIKE
NVL(p_customer_name, d.customer_name)
AND e.update_date between
NVL(to_date(p_update_date_start, 'dd-mon-rrrr'), '01-JAN-1900') AND
NVL(to_date(p_update_date_end, 'dd-mon-rrrr'), '31-DEC-2199')
AND c.doms_order_num LIKE
NVL(p_order_num, c.doms_order_num)
ORDER BY a.contract_num,
c.doms_order_num,
e.service_tag,
e.sku) LOOP
IF NOT vRecords THEN
vRecords := TRUE;
owa_util.mime_header(ccontent_type => 'application/vnd.ms-excel');
htp.htmlopen;
htp.bodyopen;
htp.tableopen(cattributes => 'border=1');
htp.tablerowopen;
htp.p('<td><b>Contract</b></td>');
htp.p('<td><b>Customer Number</b></td>');
htp.p('<td><b>Customer</b></td>');
htp.p('<td><b>Order#</b></td>');
htp.p('<td><b>Asset</b></td>');
htp.p('<td><b>SKU</b></td>');
htp.p('<td><b>Field</b></td>');
htp.p('<td><b>Previous Value</b></td>');
htp.p('<td><b>New Value</b></td>');
htp.p('<td><b>Update Date</b></td>');
htp.p('<td><b>Updated By</b></td>');
htp.tablerowclose;
END IF;
htp.tablerowopen;
htp.p('<td>' || i.contract_num || '</td>');
htp.p('<td>' || i.customer_abt_number || '</td>');
htp.p('<td>' || i.customer_name || '</td>');
htp.p('<td>' || i.order_num || '</td>');
htp.p('<td>' || i.asset || '</td>');
htp.p('<td>' || i.sku || '</td>');
htp.p('<td>' || i.field || '</td>');
htp.p('<td>' || i.previous_value || '</td>');
htp.p('<td>' || i.new_value || '</td>');
htp.p('<td>' || to_char(i.update_date, 'DD-MON-RRRR HH12:MI:SS') ||
'</td>');
htp.p('<td>' || i.updated_by || '</td>');
htp.tablerowclose;
END LOOP;
IF vRecords THEN
htp.tableclose;
htp.bodyclose;
htp.htmlclose;
END IF;
END GENERATE_REPORT_P;
But when i execute this procedure by
Begin
GENERATE_REPORT_P();
END;
I ALWAYS get this error:
I was trying to figure it out, but not much luclk until now, I've tryed to comment all the code into the procedure and just call the owa_util.mime_header(ccontent_type => 'application/vnd.ms-excel'); To see what happens, and checked the data type from my table, well, pretty much all the basic stuff.
If anyone could give me some help, ou tip, i really appreciate that.
My Regards!
Note: I extract the procedure from a packge, and ajust one or two things just to place at StackOverflow, so, i u see the error message and figere it out, my bad!
To resolve this particular issue put this piece of code somewhere before the call to generate_report_p:
owa.num_cgi_vars := NVL(owa.num_cgi_vars, 0);