ORA-19279 XPTY0004 - Xquery dynamic type mismatch: expected singleton sequence - got multi-item sequence - oracle11g

I have next below xml message in CLOB column:
<Message type="Close Subscription" creationdatetime="15/01/2010 07:48" market="01" xmlns="http://test.org/">
<Customer userId="data" market="01">
<UserAccount>test#hotmail.com</UserAccount>
<ExpireDate>15/02/2016 07:48:11</ExpireDate>
<Member>
<MemberReferency number="000003" digit="85" market="01" name="John Rambo"/>
</Member>
<Email Id="700">
<Address>test#hotmail.com</Address>
<IsConfirmed>True</IsConfirmed>
<Privacies>
<Privacy type="C" value="I"/>
<Privacy type="M" value="I"/>
</Privacies>
</Email>
<Newsletter mailService="NL">
<language>N</language>
<frequency>0</frequency>
<promotion/>
<origin/>
</Newsletter>
</Customer>
</Message>
For this xml message, I have twice the xml tag privacy
<Privacies>
<Privacy type="C" value="I"/>
<Privacy type="M" value="T"/>
</Privacies>
How can I get the value of privacy for only one of them without fetch the error?.
I mean, to get the privacy of the type='C'.
Now I'm using next below query that contain the error:
select Privacy
from (select *
from ta_gen.notification_log a,
XMLTable(XMLNAMESPACES('http://test.org/' AS "XML"),
'/XML:Message' passing xmltype(NTL_MSG) columns
Privacy VARCHAR2(1) path 'XML:Customer/XML:Email/XML:Privacies/XML:Privacy/#value') O
where a.ntl_type = 'Message')
NOTE: When the xml tag privacy is once in the xml message, the error is not raised.

Depending on what you want to happen when there is only an M-type node, you canb either search explicitly for the type attribute being C:
select x.privacy
from notification_log a
cross join XMLTable(XMLNamespaces('http://test.org/' AS "XML"),
'/XML:Message'
passing XMLType(ntl_msg)
columns privacy varchar2(1)
path 'XML:Customer/XML:Email/XML:Privacies/XML:Privacy[#type="C"]/#value') x
where a.ntl_type = 'Message';
PRIVACY
-------
I
Or you can extract the type and value for all privacy nodes via a second level of XMLTable, and then decide which to keep:
select min(x2.privacy) keep (dense_rank first order by x2.type) as privacy
from notification_log a
cross join XMLTable(XMLNamespaces('http://test.org/' AS "XML"),
'/XML:Message' passing XMLType(ntl_msg)
columns privacies XMLType path 'XML:Customer/XML:Email/XML:Privacies') x1
cross join XMLTable(XMLNAMESPACES('http://test.org/' AS "XML"),
'XML:Privacies/XML:Privacy'
passing privacies
columns type varchar2(1) path '#type',
privacy varchar2(1) path '#value') x2
where a.ntl_type = 'Message';
PRIVACY
-------
I
If you ran the same query but instead did select x2.type, x2.value from ... then you'd see:
TYPE PRIVACY
---- -------
C I
M I
.. and the min(x2.privacy) keep (dense_rank first order by x2.type) gets the value type from the 'lower' (according to string comparison) type value; which means it prioritises C over M if both exist, but will use either if there is only one

Related

How to get all the elements of an association?

I have created a CDS views as follows:
define view YGAC_I_REQUEST_ROLE
with parameters
pm_req_id : grfn_guid,
#Consumption.defaultValue: 'ROL'
pm_item_type : grac_prov_item_type,
#Consumption.defaultValue: 'AP'
pm_approval : grac_approval_status
as select from YGAC_I_REQ_PROVISION_ITEM as provitem
association [1..1] to YGAC_I_ROLE as _Role on _Role.RoleId = provitem.ProvisionItemId
association [1..*] to YGAC_I_ROLE_RS as _Relation on _Relation.RoleId1 = provitem.ProvisionItemId
{
key ReqId,
key ReqIdItem,
Connector,
ProvisionItemId,
ActionType,
ValidFrom,
ValidTo,
_Role.RoleId,
_Role.RoleName,
_Role.RoleType,
_Role,
_Relation
}
where
ReqId = $parameters.pm_req_id
and ProvisionItemType = $parameters.pm_item_type
and ApprovalStatus = $parameters.pm_approval
Then I have consumed in ABAP:
SELECT
FROM ygac_i_request_role( pm_req_id = #lv_test,
pm_item_type = #lv_item_type,
pm_approval = #lv_approval
)
FIELDS reqid,
connector,
provisionitemid
INTO TABLE #DATA(lt_result).
How to get the list of _Relation according to selection above.
This is generally not possible like in ABAP SQL queries:
SELECT m~*, kt~*
FROM mara AS m
JOIN makt AS kt
...
This contradicts the whole idea of CDS associations, because they were created to join on-demand and to reduce redundant calls to database. Fetching all fields negates the whole idea of "lazy join".
However, there is another syntax in FROM clause which is enabled by path expressions that allows querying underlining associations both fully and by separate elements. Here is how
SELECT *
FROM ygac_i_request_role( pm_req_id = #lv_test )
\_Role AS role
INTO TABLE #DATA(lt_result).
This fetches all the fields of _Role association into internal table.
Note: remember, it is not possible to fetch all the published associations of current view simultaneously, only one path per query.
Possible workaround is to use JOIN
SELECT *
FROM ygac_i_request_role AS main
JOIN ygac_i_request_role
\_Role AS role
ON main~ProvisionItemId = role~RoleId
JOIN ygac_i_request_role
\_Relation AS relation
ON main~ProvisionItemId = relation~RoleId1
INTO TABLE #DATA(lt_table).
This creates deep-structured type with dedicated structure for every join association like this:
If you are not comfortable with such structure for you task, lt_table should be declared statically to put up all the fields in a flat way
TYPES BEGIN OF ty_table.
INCLUDE TYPE ygac_i_request_role.
INCLUDE TYPE ygac_i_role.
INCLUDE TYPE ygac_i_role_rs.
TYPES END OF ty_table.

SQLite + Mybatis-guice throw ArrayIndexOutOfBoundsException

I'm trying to implement a Guice module that to lets Guacamole use SQLite as a backend. The Guacamole project has a generic JDBC base module. This lets you implement modules for specific datastores with less code. Most of the lines of code end up being in mapper XML files. The project provides PostgreSQL and MySQL implementations.
I based this SQLite module off of the MySQL module. For the mapper XML files, SQLite and MySQL are similar enough that I didn't have to make any changes. However, when I try to use the SQLite module, I get this error:
### Error querying database. Cause: java.lang.ArrayIndexOutOfBoundsException: 2
### The error may exist in org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT guacamole_connection_group.connection_group_id, connection_group_name, parent_id, type, max_connections, max_connections_per_user, enable_session_affinity FROM guacamole_connection_group JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id WHERE guacamole_connection_group.connection_group_id IN ( ? ) AND user_id = ? AND permission = 'READ'; SELECT parent_id, guacamole_connection_group.connection_group_id FROM guacamole_connection_group JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id WHERE parent_id IN ( ? ) AND user_id = ? AND permission = 'READ'; SELECT parent_id, guacamole_connection.connection_id FROM guacamole_connection JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id WHERE parent_id IN ( ? ) AND user_id = ? AND permission = 'READ';
### Cause: java.lang.ArrayIndexOutOfBoundsException: 2
It looks like the problem is that two parameters are passed to the query, but each is repeated three times. When MyBatis generates the PreparedStatement, it acts as if there are six parameters that needed to be passed in.
Here's the query it has a problem with:
<!-- Select multiple connection groups by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections">
SELECT
guacamole_connection_group.connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM guacamole_connection_group
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
WHERE guacamole_connection_group.connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, guacamole_connection_group.connection_group_id
FROM guacamole_connection_group
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
SELECT parent_id, guacamole_connection.connection_id
FROM guacamole_connection
JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
AND user_id = #{user.objectID,jdbcType=INTEGER}
AND permission = 'READ';
</select>
If I manually populate the parameters, I can execute this against the SQLite database. Also, the MySQL version works fine.
What the heck is going on? What can I do to debug this? Is it a MyBatis problem or something with the JDBC connector?
If it helps, you can see the code for the module here.
Here's the method for the parameter the mapper related to this query. The full mapper classes for ConnectionGroup are here and here. The full mapper XML for my SQLite module is here.
Collection<ModelType> selectReadable(#Param("user") UserModel user,
#Param("identifiers") Collection<String> identifiers);
This is what the ConnectionGroupResultMap looks like:
<resultMap id="ConnectionGroupResultMap" type="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel" >
<!-- Connection group properties -->
<id column="connection_group_id" property="objectID" jdbcType="INTEGER"/>
<result column="connection_group_name" property="name" jdbcType="VARCHAR"/>
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
<result column="type" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.ConnectionGroup$Type"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="enable_session_affinity" property="sessionAffinityEnabled" jdbcType="BOOLEAN"/>
<!-- Child connection groups -->
<collection property="connectionGroupIdentifiers" resultSet="childConnectionGroups" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_group_id"/>
</collection>
<!-- Child connections -->
<collection property="connectionIdentifiers" resultSet="childConnections" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_id"/>
</collection>
</resultMap>
David,
I know this is a little old, but I'm also trying to implement a SQLite JDBC module, and ran into exactly the same problem. I've managed to track down the source of the issue, and have filed an issue on the JDBC SQLite github page:
https://github.com/xerial/sqlite-jdbc/issues/277
Basically, the SQLite JDBC driver computes one of its array sizes based on the parameter count for a prepared statement. However, in the cases you mentioned, there are multiple SELECT statements which take the same parameters, so the array needs to be x * y (x = parameter count, y = number of select statements) rather than just the number of parameters. When it tries to prepare the statement, it hits the first position beyond the parameter count and generates this exception.
The other JDBC modules - MySQL, PostgreSQL, and SQL Server, as well as Oracle and H2 that I'm messing with - seem to handle this situation correctly (well, Oracle is a little...special...), but the SQLite driver does not.
I was able to work around the issue in a really, really kludgy way, by creating two different result maps, one for the generic select and one for the read that checks for READ permissions, and then break out each of the select queries into its own SELECT block and call those from the collection inside the result map. It's nowhere near as elegant as the existing code, but it works.

XQuery : OBJECT_VALUE invalid identifier

I've created a table
Movie ( title varchar2(40), review XMLTYPE)
And review has: `
<review>
<reviewer>...</reviewer>
<title> ....</title>
<rating>.....</rating> </Review> </reviewer>
When I try to access :
SELECT X.reviewername FROM movie m, XMLTABLE ('for $d in /reviews/review
return $d'
PASSING OBJECT_VALUE
columns
reviewername VARCHAR2(50) PATH 'reviewer') AS X
I get an error at OBJECT_VALUE. Where am I going wrong?
EDIT: I changed the Query to
SELECT m.title,
warehouse2.*
FROM movie M,
XMLTABLE('/REVIEW'
PASSING m.reviews
COLUMNS
"Rail" varchar2(60) PATH '//RATING')
warehouse2;
But no rows are getting selected. Any suggestions?
Well for one thing, don't you have a typo: '/reviews/review ' ? there is no element called anywhere in your example.
Your XML isn't well formed, you have overlapping tags, you have mismatched reviews/Reviews (XML is case sensitive) and in your query you have reviews/review but your xml has /review (no s on the end). –

SELECT * ... WHERE col="string" returns invalid row

I'm getting a confusing select...where result, the table definition is:
CREATE TABLE modes (
key INTEGER,
mode INTEGER,
channel INTEGER,
name TEXT,
short_name TEXT,
def INTEGER,
highlight INTEGER,
catagory TEXT,
subcatagory TEXT);
It's populated with:
sqlite> select * from modes;
3|6|5|Green|G|0|255|a|b
3|6|6|Blue|B|0|255|a|b
3|9|1|Mode|Mode|0|255|a|b
3|9|2|Auto Mode Speed|Speed|0|255|a|b
3|9|3|Strobe|Strobe|0|255|a|b
3|9|4|Red|R|0|255|a|b
3|9|5|Green|G|0|255|a|b
3|9|6|Blue|B|0|255|a|b
3|9|7|Red2|R2|0|255|a|b
3|9|8|Green2|G2|0|255|a|b
3|9|9|Blue2|B2|0|255|a|b
3|6|4|Red|R|0|255|a|b
3|6|1|6|6|0|255|a|b
3|6|2|Auto mode speed|speed|0|255|a|b
3|6|3|Strobe|Strobe|0|255|strobe|b
Note the row 3rd from the bottom:
3|6|1|6|6|0|255|a|b
If I do a select:
SELECT * FROM modes where mode=6 and name="Mode" order by channel;
It returns:
3|6|1|6|6|0|255|a|b
Columns 4 and 5 (name and short_name) should not match, they are 6 and the match term is "Mode". If I change the match string "Mode" to any other string it works as expected. Is "Mode" a reserved word? or Did I somehow set a variable "Mode" to 6?. I don't understand this behavior.
If you use ["] it means columns, so when you do
name="Mode"
it means you search in column name that have same value as column Mode. So you select where mode=6 and name=6 actually on your code.
If you want to use string, use ['] not ["]
I try to use that code on my database..
select * from products
where name="Mode"
And I got error
ERROR: column "Mode" does not exist
LINE 2: where name="Mode"
I finally found it in the docs if anyone else is looking.
it's in the the sqlite3 FAQ
My familiarity is not with sqlite3, but I would say that it looks to me like you are doing name="Mode" which is taking the modes.mode object and checking it.
If you do SELECT * FROM modes where name="Mode" order by channel. You may find that it just gives you 3|6|1|6|6|0|255|a|b as well.

Query to output content of AllXml column of ELMAH_Error sql server table

I am having trouble writing query so that I can query the content of AllXml column inside Elmah_Error table.
How can I list out all the item nodes as an output of the query.
How could I write query to only list for certain item nodes?
I would like to get follow resultset:
item value
===== =====
ALL_HTTP HTTP_CONNECTION:xxxx
ALL_RAW Connection: xxxxx
I would also like to be able to filter the query by ErrorID
Content of AllXml column may look like this.
<error
application="/"
message="hello world"
source="TestWebElmah"
detail="xxxxx">
<serverVariables>
<item
name="ALL_HTTP">
<value
string="HTTP_CONNECTION:xxxx" />
</item>
<item
name="ALL_RAW">
<value
string="Connection: xxxxx" />
</item>
</serverVariables>
</error>
Remote Addr nodes
select T.N.value('(value/#string)[1]', 'varchar(30)') as REMOTE_ADDR
from
(select cast(AllXml as xml) as AllXml from ELMAH_Error) e
cross apply AllXml.nodes('//item[#name="REMOTE_ADDR"]') as T(N)
HTTP User Agents which contain mozilla
select T.N.value('(value/#string)[1]', 'varchar(30)') as HTTP_USER_AGENT
from
(select cast(AllXml as xml) as AllXml from ELMAH_Error) e
cross apply AllXml.nodes('//item[#name="HTTP_USER_AGENT"]') as T(N)
where T.N.value('(value/#string)[1]', 'varchar(30)') like '%mozilla%'
Elmah table stores the AllXml column as nvarchar so it needs to be casted to xml
all tags + values, by error id
select T.N.value('#name', 'varchar(30)') as Name,
T.N.value('(value/#string)[1]', 'varchar(30)') as Value
from
(select cast(AllXml as xml) as AllXml from ELMAH_Error where ErrorId = 'DC82172B-F2C0-48CE-8621-A60B702ECF93') e
cross apply AllXml.nodes('/error/serverVariables/item') as T(N)
Before voting down this answer, because uses most of the part of Mikael Eriksson's answer, I let you know I'll happily accept the downvotes only for this reason, since is mainly true
This query will give you all item nodes
select T.N.value('#name', 'varchar(30)') as Name,
T.N.value('(value/#string)[1]', 'varchar(30)') as Value
from Elmah_Error
cross apply AllXml.nodes('/error/serverVariables/item') as T(N)
If you want to filter on any of the values you can put that in a sub-query apply a regular where clause.
select Name,
Value
from
(
select T.N.value('#name', 'varchar(30)') as Name,
T.N.value('(value/#string)[1]', 'varchar(30)') as Value
from Elmah_Error
cross apply AllXml.nodes('/error/serverVariables/item') as T(N)
) T
where Name = 'ALL_HTTP'

Resources