I'm not sure that this case is valid at all right now, since as for now,
Ignite doesn't support transactions for SQL.

Evgenii

2018-07-24 13:36 GMT+03:00 Maxim Malygin <maxim.maly...@gmail.com>:

> Hi Evgenii,
>
> Thanks for the answer.
> Unfortunately it seems it does matter. If I do a query inside a
> transaction and use an instance of a cache that differs of a cache inside
> the query, I will get the following exception (note I do it on client node):
>
> Exception in thread "main" javax.cache.CacheException: Cannot start/stop
> cache within lock or transaction.
>         at org.apache.ignite.internal.processors.cache.
> IgniteCacheProxyImpl.query(IgniteCacheProxyImpl.java:676)
>         at org.apache.ignite.internal.processors.cache.
> IgniteCacheProxyImpl.query(IgniteCacheProxyImpl.java:615)
>         at org.apache.ignite.internal.processors.cache.
> GatewayProtectedCacheProxy.query(GatewayProtectedCacheProxy.java:356)
>         at simax.test.Startup.main(Startup.java:39)
> Caused by: class org.apache.ignite.IgniteException: Cannot start/stop
> cache within lock or transaction.
>         at org.apache.ignite.internal.processors.cache.GridCacheProcessor.
> checkEmptyTransactions(GridCacheProcessor.java:4251)
>         at org.apache.ignite.internal.processors.cache.GridCacheProcessor.
> dynamicStartCache(GridCacheProcessor.java:2942)
>         at org.apache.ignite.internal.processors.cache.GridCacheProcessor.
> dynamicStartCache(GridCacheProcessor.java:2884)
>         at org.apache.ignite.internal.processors.cache.GridCacheProcessor.
> createMissingQueryCaches(GridCacheProcessor.java:4114)
>         at org.apache.ignite.internal.processors.query.h2.
> IgniteH2Indexing.prepareStatementAndCaches(IgniteH2Indexing.java:2017)
>         at org.apache.ignite.internal.processors.query.h2.
> IgniteH2Indexing.parseAndSplit(IgniteH2Indexing.java:1796)
>         at org.apache.ignite.internal.processors.query.h2.
> IgniteH2Indexing.querySqlFields(IgniteH2Indexing.java:1652)
>         at org.apache.ignite.internal.processors.query.
> GridQueryProcessor$4.applyx(GridQueryProcessor.java:2035)
>         at org.apache.ignite.internal.processors.query.
> GridQueryProcessor$4.applyx(GridQueryProcessor.java:2030)
>         at org.apache.ignite.internal.util.lang.IgniteOutClosureX.
> apply(IgniteOutClosureX.java:36)
>         at org.apache.ignite.internal.processors.query.GridQueryProcessor.
> executeQuery(GridQueryProcessor.java:2578)
>         at org.apache.ignite.internal.processors.query.GridQueryProcessor.
> querySqlFields(GridQueryProcessor.java:2044)
>         at org.apache.ignite.internal.processors.cache.
> IgniteCacheProxyImpl.query(IgniteCacheProxyImpl.java:664)
>
> It seems the issue is in starting cache used in the query. If I get
> IgniteCache instance for that cache, it will be started before the
> transaction. But if it's never used in Ignite.cache(..) or
> ignite.getOrCreateCache(..), the cache will be started inside query(..)
> method which is executed in the transaction and I will get the above listed
> exception. As workaround, I need to pre-initialize all caches used in
> queries using either Ignite.cache(..) or ignite.getOrCreateCache(..). Note
> that all caches are configured in XML configuration on server nodes only
> but the queries is executed on a client node.
>
> The code is very simple:
>
> public class Startup {
>     private static final Logger log = LogManager.getLogger(Startup.class);
>
>     public static void main(String[] args) {
>        boolean client = args.length >= 1 && "client".equalsIgnoreCase(
> args[0]);
>        Ignite ignite;
>         if (client) {
>             log.info("Starting client node...");
>             ignite = Ignition.start("client.xml");
>         } else {
>             log.info("Starting server node...");
>             ignite = Ignition.start("server.xml");
>         }
>         log.info("Cache names: " + ignite.cacheNames());
>         IgniteCache<?, ?> cache1 = ignite.cache("Cache1");
>
>         try (Transaction tx = ignite.transactions().txStart()) {
>             // query from cache1 using instance of cache1
>             List<List<?>> r1 = cache1.query(new SqlFieldsQuery("SELECT *
> FROM Cache1")).getAll(); // No exception here because Cache1 is already
> initialized by ignite.cache("Cache1")
>             log.info("Result from cache1: " + r1);
>         }
>
>         try (Transaction tx = ignite.transactions().txStart()) {
>             // query from cache2 using instance of cache1
>             List<List<?>> r2 = cache1.query(new SqlFieldsQuery("SELECT *
> FROM Cache2")).getAll(); // <<< Got exception here if invoked on client
> node (clientMode=true)
>             log.info("Result from cache2: " + r2);
>         }
>     }
> }
>
> client.xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns="http://www.springframework.org/schema/beans";
>        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
>        xmlns:context="http://www.springframework.org/schema/context";
>        xsi:schemaLocation="http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-4.3.xsd";>
>     <bean class="org.apache.ignite.configuration.IgniteConfiguration">
>         <property name="clientMode" value="true"/>
>     </bean>
> </beans>
>
> server.xml:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns="http://www.springframework.org/schema/beans";
>        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
>        xmlns:context="http://www.springframework.org/schema/context";
>        xsi:schemaLocation="http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-4.3.xsd";>
>     <bean class="org.apache.ignite.configuration.IgniteConfiguration">
>         <property name="clientMode" value="false"/>
>         <property name="cacheConfiguration">
>             <list>
>                 <bean class="org.apache.ignite.configuration.
> CacheConfiguration">
>                     <property name="name" value="Cache1"/>
>                     <property name="sqlSchema" value="PUBLIC"/>
>                     <property name="queryEntities">
>                         <list>
>                             <bean class="org.apache.ignite.
> cache.QueryEntity">
>                                 <property name="keyType"
> value="Cache1Key"/>
>                                 <property name="keyFields">
>                                     <set>
>                                         <value>id1</value>
>                                         <value>id2</value>
>                                     </set>
>                                 </property>
>                                 <property name="valueType" value="Cache1"/>
>                                 <property name="fields">
>                                     <map>
>                                         <entry key="id1"
> value="java.lang.String"/>
>                                         <entry key="id2"
> value="java.lang.String"/>
>                                         <entry key="aaa"
> value="java.lang.String"/>
>                                         <entry key="bbb"
> value="java.lang.String"/>
>                                         <entry key="ccc"
> value="java.lang.String"/>
>                                     </map>
>                                 </property>
>                             </bean>
>                         </list>
>                     </property>
>                 </bean>
>                 <bean class="org.apache.ignite.configuration.
> CacheConfiguration">
>                     <property name="name" value="Cache2"/>
>                     <property name="sqlSchema" value="PUBLIC"/>
>                     <property name="queryEntities">
>                         <list>
>                             <bean class="org.apache.ignite.
> cache.QueryEntity">
>                                 <property name="keyType"
> value="Cache2Key"/>
>                                 <property name="keyFields">
>                                     <set>
>                                         <value>id3</value>
>                                         <value>id4</value>
>                                     </set>
>                                 </property>
>                                 <property name="valueType" value="Cache2"/>
>                                 <property name="fields">
>                                     <map>
>                                         <entry key="id3"
> value="java.lang.String"/>
>                                         <entry key="id4"
> value="java.lang.String"/>
>                                         <entry key="xxx"
> value="java.lang.String"/>
>                                         <entry key="yyy"
> value="java.lang.String"/>
>                                         <entry key="zzz"
> value="java.lang.String"/>
>                                     </map>
>                                 </property>
>                             </bean>
>                         </list>
>                     </property>
>                 </bean>
>             </list>
>         </property>
>     </bean>
> </beans>
>
> Maybe I do something incorrectly?
>
> Thanks,
> Maxim
>
> пн, 23 июл. 2018 г. в 17:51, Evgenii Zhuravlev <e.zhuravlev...@gmail.com>:
>
>> Hi Maxim,
>>
>> It doesn't matter, which cache you will use for SQL queries here, so,
>> yes, you can use some dummy cache. In future, afaik, there are plans to
>> change this API, the method will be placed in Ignite class instead of
>> IgniteCache.
>>
>> Regards,
>> Evgenii
>>
>> 2018-07-23 17:41 GMT+03:00 Maxim Malygin <maxim.maly...@gmail.com>:
>>
>>> Hi,
>>>
>>> I have the question regarding Java API for SQL queries.
>>> As I understand from the documentation, API for SQL queries is placed in
>>> IgniteCache interface ("query" method). This means that I need to get or
>>> create a cache to do a SQL query. What cache name I should use to get
>>> instance of IgniteCache? Some dummy cache?
>>>
>>> Thanks,
>>> Maxim
>>>
>>
>>

Reply via email to