How do I read data from Ignite KV-storage using jdbc? - sql

It is ok putting/getting data from KV-store for me, using custom class for value.
Also it is ok INSERTING/SELECTING data from table, created using jdbc. This way i'm getting cache named SQL_PUBLIC_TABLENAME.
But I can't find way to INSERT/SELECT data from KV-store using SQL queries. I've created custom value class and defined fields using #QuerySqlField annotation like that:
#QuerySqlField(index = true)
public Integer id;
#QuerySqlField(index = true)
public String records_offset;
#QuerySqlField(index = true)
public Integer session_id;
Then I defined cache using xml-config this way:
<property name="cacheConfiguration">
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<!-- Set a cache name. -->
<property name="name" value="test"/>
<property name="queryEntities">
<list>
<bean class="org.apache.ignite.cache.QueryEntity">
<property name="keyType" value="java.lang.Integer"/>
<property name="valueType" value="CDR"/>
<property name="tableName" value="CDR"/>
<property name="fields">
<map>
<entry key="id" value="java.lang.Long"/>
<entry key="records_offset" value="java.lang.String"/>
<entry key="session_id" value="java.lang.Integer"/>
</map>
</property>
</bean>
</list>
</property>
<!-- Set cache mode. -->
<property name="cacheMode" value="PARTITIONED"/>
</bean>
</property>
I've got cache that I can put/get data in/from, and also I can connect to Ignite using sqlline tool, where I can see CDR table (among others created throug jdbc) with test schema:
0: jdbc:ignite:thin://127.0.0.1/> !tables
+--------------------------------+--------------------------------+--------------------------------+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME |
+--------------------------------+--------------------------------+--------------------------------+
| | PUBLIC | CITY |
| | test | CDR |
| | PUBLIC | PERSON |
| | PUBLIC | TEST2 |
| | PUBLIC | LOL |
| | PUBLIC | TEST |
+--------------------------------+--------------------------------+--------------------------------+
But I can't neither read nor put data into that CDR table:
0: jdbc:ignite:thin://127.0.0.1/> DROP table CDR;
Error: Table doesn't exist: CDR (state=42000,code=0)
java.sql.SQLException: Table doesn't exist: CDR
at org.apache.ignite.internal.jdbc.thin.JdbcThinConnection.sendRequest(JdbcThinConnection.java:671)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute0(JdbcThinStatement.java:130)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute(JdbcThinStatement.java:299)
at sqlline.Commands.execute(Commands.java:823)
at sqlline.Commands.sql(Commands.java:733)
at sqlline.SqlLine.dispatch(SqlLine.java:795)
at sqlline.SqlLine.begin(SqlLine.java:668)
at sqlline.SqlLine.start(SqlLine.java:373)
at sqlline.SqlLine.main(SqlLine.java:265)
0: jdbc:ignite:thin://127.0.0.1/> select * from CDR;
Error: Failed to parse query: select * from CDR (state=42000,code=0)
java.sql.SQLException: Failed to parse query: select * from CDR
at org.apache.ignite.internal.jdbc.thin.JdbcThinConnection.sendRequest(JdbcThinConnection.java:671)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute0(JdbcThinStatement.java:130)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute(JdbcThinStatement.java:299)
at sqlline.Commands.execute(Commands.java:823)
at sqlline.Commands.sql(Commands.java:733)
at sqlline.SqlLine.dispatch(SqlLine.java:795)
at sqlline.SqlLine.begin(SqlLine.java:668)
at sqlline.SqlLine.start(SqlLine.java:373)
at sqlline.SqlLine.main(SqlLine.java:265)
0: jdbc:ignite:thin://127.0.0.1/> insert into CDR(ID, RECORDS_OFFSET, SESSION_ID) values (23, '12', 123);
Error: Failed to parse query: insert into CDR(ID, RECORDS_OFFSET, SESSION_ID) values (23, '12', 123) (state=42000,code=0)
java.sql.SQLException: Failed to parse query: insert into CDR(ID, RECORDS_OFFSET, SESSION_ID) values (23, '12', 123)
at org.apache.ignite.internal.jdbc.thin.JdbcThinConnection.sendRequest(JdbcThinConnection.java:671)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute0(JdbcThinStatement.java:130)
at org.apache.ignite.internal.jdbc.thin.JdbcThinStatement.execute(JdbcThinStatement.java:299)
at sqlline.Commands.execute(Commands.java:823)
at sqlline.Commands.sql(Commands.java:733)
at sqlline.SqlLine.dispatch(SqlLine.java:795)
at sqlline.SqlLine.begin(SqlLine.java:668)
at sqlline.SqlLine.start(SqlLine.java:373)
at sqlline.SqlLine.main(SqlLine.java:265)
0: jdbc:ignite:thin://127.0.0.1/>

You need to use schema name to access this table:
select * from "test".CDR;
or
select * from "test.CDR";
Also, if this won't help, try to set CacheConfiguration.setSqlSchema using uppercase, for example, "PUBLIC" and use this schema name

Related

Q. How to select named element values from XSD string field

Within SQL Server I'm trying to select values from what I think is a XSD string.
e.g. Given the following SQL Server table
CREATE TABLE dbo.TextXML (
ID INT PRIMARY KEY,
Data NVARCHAR(max))
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 1,
('<element name="Rownum" value="Row23" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="1234" />
</element>
<element name="ENABLESSL" value="false" />' )
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 2,
('<element name="Rownum" value="Row24" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="5678" />
</element>
<element name="ENABLESSL" value="true" />' );
I want to be able to select the values for given element names. Something like ...
SELECT ID, Data.CONNECTIONTYPESECTION, Data.EchoData.0007, Data.EchoData.MessageType, Data.ENABLESSL
FROM TextXML
WHERE Data.Rownum = "Row23" AND Data.EchoData.MessageType = "1234".
ID Data.CONNECTIONTYPESECTION Data.EchoData.0007 Data.EchoData.MessageType Data.ENABLESSL
1 True 0805193143 1234 true
I can use CHARINDEX and SUBSTRING but have to hardcode the length of the "name" value and this asumes the "value" is always the same length. I'm hoping there is a better and more efficient way do do this.
I have experimented with CROSS APPPLY and XML VALUE functions but this only returns the first element in the Data field. I also could not find out how to search for a particular element "name" to get its value
Please try the following T-SQL.
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, Data NVARCHAR(max));
INSERT INTO #tbl (Data) VALUES
(N'<element name="Rownum" value="Row23"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="1234"/>
</element>
<element name="ENABLESSL" value="false"/>'),
(N'<element name="Rownum" value="Row24"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="5678"/>
</element>
<element name="ENABLESSL" value="true"/>');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT *
, TRY_CAST(data AS XML) AS xmldata
FROM #tbl
)
SELECT rs.ID
, xmldata.value('(element[#name="CONNECTIONTYPESECTION"]/#value)[1]','VARCHAR(10)') AS CONNECTIONTYPESECTION
, xmldata.value('(element[#name="EchoData"]/element[#name="0007"]/#value)[1]','VARCHAR(10)') AS [EchoData.0007]
, xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') AS [EchoData.MessageType]
, xmldata.value('(element[#name="ENABLESSL"]/#value)[1]','VARCHAR(10)') AS [Data.ENABLESSL]
FROM rs
WHERE xmldata.value('(element[#name="Rownum"]/#value)[1]','VARCHAR(30)') = 'Row23'
AND xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') = '1234';
Output
+----+-----------------------+---------------+----------------------+----------------+
| ID | CONNECTIONTYPESECTION | EchoData.0007 | EchoData.MessageType | Data.ENABLESSL |
+----+-----------------------+---------------+----------------------+----------------+
| 1 | True | 0805193143 | 1234 | false |
+----+-----------------------+---------------+----------------------+----------------+

Reason: liquibase.exception.DatabaseException: ERROR: syntax error at or near "," for liquibase loadUpdateData with data using quotchar

I'm getting this error
mental-app_1 | Reason: liquibase.exception.DatabaseException: ERROR: syntax error at or near ","
mental-app_1 | Position: 55 [Failed SQL: DO
mental-app_1 | $$
mental-app_1 | BEGIN
mental-app_1 | UPDATE public.training SET active_since = , active_until = , conditions = 'obj.trainingColumns = [1,2];', game_id = 28, identificator = '3_1', subject_id = 1 WHERE id = 1;
mental-app_1 | IF not found THEN
mental-app_1 | INSERT INTO public.training (id, active_since, active_until, identificator, conditions, game_id, subject_id) VALUES (1, , , '3_1', 'obj.trainingColumns = [1,2];', 28, 1);
mental-app_1 | END IF;
mental-app_1 | END;
mental-app_1 | $$
mental-app_1 | LANGUAGE plpgsql;]
when executing the below part of changeset
<loadUpdateData onlyUpdate="true" quotchar='"'
file="config/liquibase/data/training.csv"
separator=";"
tableName="training" primaryKey="id">
<column name="id" type="numeric"/>
<column name="active_since" type="datetime"/>
<column name="active_until" type="datetime"/>
<column name="identificator" type="string"/>
<column name="conditions" type="string"/>
<column name="game_id" type="numeric"/>
<column name="subject_id" type="numeric"/>
<!-- jhipster-needle-liquibase-add-loadcolumn - JHipster (and/or extensions) can add load columns here, do not remove-->
</loadUpdateData>
for this kind of data
id;active_since;active_until;identificator;conditions;game_id;subject_id
1;;;3_1;"obj.trainingColumns = [1,2];";28;1
What is wrong with changeset set up of with dataset?
Change to
id;active_since;active_until;identificator;conditions;game_id;subject_id
1;"";"";3_1;"obj.trainingColumns = [1,2];";28;1
causes the same. That is PostgreSQL.
Despite of it is still unclear, why the exception is thrown, I have succeed with removing active_since and active_to columns from the dataset and removing them from the changeset conf. But until I've got quoted string for conditions column like this "obj.trainingColumns = [1,2];" it was ok with empty active_since and active_to. So, coexistence of "obj.trainingColumns = [1,2];" and empty for that fields is critical there

Extracting XML sub-tags from a clob in Oracle via SQL

I have the following CLOB XML Fragment in the DB attribute "object_body":
<object stamp="8fc630bd-f1f5-43ac-b9d2-3b9db9054c75_1481811010527" type="Aggregation" version="12">
<property name="name" value="COA_Cash_Position" valueType="string"/>
<property name="description" value="COA_Cash_Position" valueType="string"/>
<property name="objectId" value="ef4296f1-6af6-4de8-83fe-fa01cf327d87" valueType="string"/>
<property name="branchId" value="01ecc9ed-27f3-42cb-a44d-2cec221ec8fa" valueType="string"/>
<property name="models" valueType="table">
<object type="ModelBasedTask:modelEntry" version="3">
<property name="dataModel" valueType="url">DataModel["ModifyModel[COA_Cash_Positions_BHS_Unadjusted].STAGING:X_NRS_BSL40K_BHS"{ModifyModel[ff81e5f2-2ef6-437a-b113-67f7c0dd5e53].cdf308fc-520d-4611-a8db-4e6863e216b8:9ffcd08e-732a-4270-b15f-f4775bcc69db}]</property>
<property name="instanceSelectionRule" valueType="object">
<object type="InstanceSelectionRule" version="3">
<property name="instanceDateRule" valueType="object">
<object type="InstanceSelectionRule:rule" version="3">
<property name="type" value="EQUAL" valueType="string"/>
</object>
</property>
<property name="instanceKeyRules" valueType="table"/>
</object>
</property>
</object>
</property>
</object>
Aim is to extract the value of the property tag with name=”description”
=> to produce “COA_Cash_Position”
Tried all variations of:
EXTRACTVALUE(xmltype(object.object_body), '/object/property[#name="description"].getStringVal()'),
If I loose the .getStringVal() the query works but obviously only provides empty results (as the property tag itself doesn't include any value).
Get mostly error messages the likes of:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00601: Invalid token in: '/object/property[#name="description"].
getStringVal()'
What easily works is extracting the values between two xml tags but getting a specific property value (like here the "value" of the tag with name="description") seems to evade the XML extract possibilities.
Any help is warmly appreciated...
EXTRACTVALUE is deprecated in Oracle 12 - it is being replaced by XMLTABLE or XMLQUERY.
SELECT x.description
FROM your_table t
CROSS JOIN
XMLTABLE(
'//object/'
PASSING XMLTYPE( t.your_clob_column )
COLUMNS description VARCHAR2(4000) PATH './property[#name="description"]/#value'
) x;
or
SELECT XMLQUERY(
'//object/property[#name="description"]/#value'
PASSING XMLTYPE( your_clob_column )
RETURNING CONTENT
).getStringVal()
FROM your_table;
But if you do want to use EXTRACTVALUE you can do:
SELECT EXTRACTVALUE(
XMLTYPE( your_clob_column ),
'//object/property[#name="description"]/#value'
)
FROM your_table;
Assuming you mean the value of the attribute #value the path you want is
/object/property[#name='description']/#value
Your XML contains some errors.
We can achieve your expected output using REGEXP in oracle.
Check below query.
SELECT REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_SUBSTR (object_body, 'description" value=".*.".v', 1), 'description" value="', '', 1, 1) ,'" v','',1,1)
FROM Table
Check Demo here.
Output IS: COA_Cash_Position

JdbcPagingItemReader with multiple select query

I 'd like to write a JdbcPagingItemReader with a complex query like:
select xxx from yyy where a=b and c = (select max(f) from yyy where a=b)
...with parameters.
Here is how I wrote my query:
<bean
class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="selectClause" value="SELECT ohrefnum" />
<property name="fromClause" value="FROM orderhdr_all" />
<property name="whereClause"
value="WHERE customer_id =: CUSTOMER_ID AND ohentdate = (SELECT MAX (ohentdate) FROM orderhdr_all WHERE customer_id =: CUSTOMER_ID)" />
<property name="sortKey" value="ohrefnum" />
</bean>
but it raise the following error: java.sql.SQLException: Missing IN or OUT parameter at index:: 2
I found the problem origin. It was simply the space character after the "=:"
It should be
WHERE customer_id =:CUSTOMER_ID)
and not
WHERE customer_id =: CUSTOMER_ID)

performance is slow while running a DB query using Struts

I am using Struts to build a web application. Application server is Tomcat Server 6, database is Oracle 11G. I am executing an action class which contains the following DB query:
SELECT BV_USER__TEMP.CEC_ID AS USER_ID,
BV_USER_BEHRCHY_TEMP.LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM__HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR =
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME)
WHERE IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND IAM_LEVEL_NUM=2
AND USER_ID=?
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT CEC_ID AS USER_ID,
BUSINESS_ENTITY_HIER_NAME.IAM_LEVEL_NUM AS LEVEL_NUM,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BUSINESS_ENTITY_NAME=BUSINESS_ENTITY_HIER_NAME)
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=1
AND USER_id=2
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT BV_USER_BE_HRCHY_TEMP.USER_ID,
BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM_ENTITY_HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
CROSS JOIN BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR BSE
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=0
AND USER_ID=?
GROUP BY 1,2,3,4,5,6;
In applicationContext.xml the bean:
<bean id="tablOrclDataSourceRead" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:oci:#********DEV" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="initialSize" value="5" />
<property name="maxActive" value="5" />
<property name="maxIdle" value="0" />
<property name="minIdle" value="0" />
<property name="maxWait" value="-1" />
</bean>
JSON returned:
{"data":[
{"keyCol":"Utah","val":"Utah"},
{"keyCol":"Seattle","val":"Seattle"},
{"keyCol":Nebraska","val":"Nebraska"},
{"keyCol":"Enterprise Networking","val":"Enterprise Networking"}
]}
The time taken to execute the action (and return the JSON) with the above query is around 21 seconds.
Please let me know if I am missing something.
The same query when executed through SQL developer returns the result set in less than a second.