I see your point. But what about my concerns from initial post?
Particularly about signatures of existing methods? I personally don't
like an option of query() method always returning an empty iterator
for any non-select query, it seems ugly design wise.

- Alex

2016-07-26 18:15 GMT+03:00 Sergi Vladykin <sergi.vlady...@gmail.com>:
> BTW, the simplest way to solve this issue is to allow running SQL commands
> inside of SqlFieldsQuery.
>
> We may add some additional convenience API for updates if we want, but JDBC
> client will always call it like this:
>
> cache.query(new SqlFieldsQuery("INSERT INTO MY_TABLE
> VALUES(?,?)").setArgs(1,2));
>
> This will resolve any ambiguity.
>
> Sergi
>
> 2016-07-26 17:56 GMT+03:00 Sergi Vladykin <sergi.vlady...@gmail.com>:
>
>> I don't like any pre-parsing, especially with some libraries other than
>> H2. H2 itself has enough quirks to multiply it on quirks of another library.
>>
>> This is exactly what I was talking about - we need some single entry point
>> on API for all the SQL commands and queries. Thats why I suggested
>> SqlUpdate to extend Query. To me its is the cleanest approach. May be we
>> need to change in some backward compatible way this Query hierarchy to get
>> rid of extra methods but the idea is still the same.
>>
>> Sergi
>>
>> 2016-07-26 14:34 GMT+03:00 Alexander Paschenko <
>> alexander.a.pasche...@gmail.com>:
>>
>>> Guys,
>>>
>>> I would like to advance the discussion further. There's one quite
>>> important question that arose based on current state of work on this
>>> issue. If we use some kind of interactive console, like Visor, then
>>> how should it know whether SQL query it is requested to execute
>>> returns a result set or not? In JDBC world, solution is quite simple -
>>> there's base interface called Statement that all commands implement,
>>> and it has magic isResultSet method that tells whether statement is a
>>> query or an update command. The API proposed now has separate Query
>>> and Update operations which I believe to be a right thing by the
>>> reasons I outlined in the beginning of this thread. However, their
>>> lack of common ancestor prevents possible console clients from running
>>> text SQL commands in a fully transparent manner - like
>>> IgniteCache.execute(String sql). Therefore I see two possible ways of
>>> solving this:
>>>
>>> - we change API so that it includes new class or interface parenting
>>> both Query and Update, and clients use it to communicate with cache
>>> - we let (or make :) ) the client determine command type independently
>>> and behave accordingly - for it to work it will have some kind of
>>> command parsing by itself just to determine its type. Visor console
>>> may use simple library like JSqlParser
>>> (https://github.com/JSQLParser/JSqlParser; dual LGPL 2.1/ASF 2.0
>>> licensed) to determine request type in terms of JDBC, and behave
>>> accordingly.
>>>
>>> Personally, I think that the second approach is better - and here's why.
>>>
>>> First, it does not seem wise to change API simply to make console (or
>>> any other) clients simpler. Programmatic APIs should be concise and
>>> short for programmatic use, console clients should be easy to use from
>>> console - and that's it: after all, console client exists to free a
>>> user from burden of doing things programmatically, so its aim is to
>>> adapt API to console or whatever UI.
>>> Second, possible complications in client implied by such approach
>>> certainly won't be dramatic - I don't think that additional single
>>> query parsing operation in client code will make it much harder to
>>> develop.
>>> Third, as I see it now, adding a new "synthetic" entity and new method
>>> would take more effort to adapting the client to new API.
>>>
>>> Dmitry, Sergi, I would like to hear what you think about it all. Thanks.
>>>
>>> - Alex
>>>
>>> 2016-07-21 21:17 GMT+03:00 Dmitriy Setrakyan <dsetrak...@apache.org>:
>>> > OK, then using your analogy, the current behavior in Ignite is MERGE for
>>> > the most part.
>>> >
>>> > My preference is that Ignite SQL should work no different from
>>> traditional
>>> > databases, which means:
>>> >
>>> > - INSERT is translated into *putIfAbsent()* call in Ignite
>>> > - UPDATE is translated into *replace()* call in Ignite
>>> > - MERGE is translated into *put()* call in Ignite
>>> > - For SQL BATCH calls we should delegate to Ignite batch operations,
>>> e.g.
>>> > *putAll()*
>>> >
>>> > The above should hold true for atomic and transactional put/putAll
>>> calls,
>>> > as well as for the data streamer.
>>> >
>>> > Does this make sense?
>>> >
>>> > D.
>>> >
>>> > On Thu, Jul 21, 2016 at 4:06 AM, Sergi Vladykin <
>>> sergi.vlady...@gmail.com>
>>> > wrote:
>>> >
>>> >> No, this does not make sense.
>>> >>
>>> >> There is no upsert mode in databases. There are operations: INSERT,
>>> UPDATE,
>>> >> DELETE, MERGE.
>>> >>
>>> >> I want to have clear understanding of how they have to behave in SQL
>>> >> databases and how they will actually behave in Ignite in different
>>> >> scenarios. Also I want to have clear understanding of performance
>>> >> implications of each decision here.
>>> >>
>>> >> Anything wrong with that?
>>> >>
>>> >> Sergi
>>> >>
>>> >> On Thu, Jul 21, 2016 at 1:04 PM, Dmitriy Setrakyan <
>>> dsetrak...@apache.org>
>>> >> wrote:
>>> >>
>>> >> > Serj, are you asking what will happen as of today? Then the answer
>>> to all
>>> >> > your questions is that duplicate keys are not an issue, and Ignite
>>> always
>>> >> > operates in **upsert** mode (which is essentially a *“put(…)”
>>> *method).
>>> >> >
>>> >> > However, the *“insert”* that is suggested by Alex would delegate to
>>> >> > *“putIfAbsent(…)”*, which in database world makes more sense.
>>> However, in
>>> >> > this case, the *“update”* syntax should delegate to *“replace(…)”*,
>>> as
>>> >> > update should fail in case if a key is absent.
>>> >> >
>>> >> > Considering the above, a notion of “*upsert”* or “*merge” *operation
>>> is
>>> >> > very much needed, as it will give a user an option to perform
>>> >> > “insert-or-update” in 1 call.
>>> >> >
>>> >> > Does this make sense?
>>> >> >
>>> >> > D.
>>> >> >
>>> >> > On Wed, Jul 20, 2016 at 9:39 PM, Sergi Vladykin <
>>> >> sergi.vlady...@gmail.com>
>>> >> > wrote:
>>> >> >
>>> >> > > I'd prefer to do MERGE operation last because in H2 it is not
>>> standard
>>> >> > ANSI
>>> >> > > SQL MERGE. Or may be not implement it at all, or may be contribute
>>> ANSI
>>> >> > > correct version to H2, then implement it on Ignite. Need to
>>> investigate
>>> >> > the
>>> >> > > semantics deeper before making any decisions here.
>>> >> > >
>>> >> > > Lets start with simple scenarios for INSERT and go through all the
>>> >> > possible
>>> >> > > cases and answer the questions:
>>> >> > > - What will happen on key conflict in TX cache?
>>> >> > > - What will happen on key conflict in Atomic cache?
>>> >> > > - What will happen with the previous two if we use DataLoader?
>>> >> > > - How to make these operations efficient (it will be simple enough
>>> to
>>> >> > > implement them with separate put/putIfAbsent operations but
>>> probably we
>>> >> > > will need some batching like putAllIfAbsent for efficiency)?
>>> >> > >
>>> >> > > As for API, we still will need to have a single entry point for
>>> all SQL
>>> >> > > queries/commands to allow any console work with it transparently.
>>> It
>>> >> > would
>>> >> > > be great if we will be able to come up with something consistent
>>> with
>>> >> > this
>>> >> > > idea on public API.
>>> >> > >
>>> >> > > Sergi
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > >
>>> >> > > On Wed, Jul 20, 2016 at 2:23 PM, Dmitriy Setrakyan <
>>> >> > > dsetrak...@gridgain.com>
>>> >> > > wrote:
>>> >> > >
>>> >> > > > Like the idea of merge and insert. I need more time to think
>>> about
>>> >> the
>>> >> > > API
>>> >> > > > changes.
>>> >> > > >
>>> >> > > > Sergi, what do you think?
>>> >> > > >
>>> >> > > > Dmitriy
>>> >> > > >
>>> >> > > >
>>> >> > > >
>>> >> > > > On Jul 20, 2016, at 12:36 PM, Alexander Paschenko <
>>> >> > > > alexander.a.pasche...@gmail.com> wrote:
>>> >> > > >
>>> >> > > > >> Thus, I suggest that we implement MERGE as a separate
>>> operation
>>> >> > backed
>>> >> > > > by putIfAbsent operation, while INSERT will be implemented via
>>> put.
>>> >> > > > >
>>> >> > > > > Sorry, of course I meant that MERGE has to be put-based, while
>>> >> INSERT
>>> >> > > > > has to be putIfAbsent-based.
>>> >> > > > >
>>> >> > > > > 2016-07-20 12:30 GMT+03:00 Alexander Paschenko
>>> >> > > > > <alexander.a.pasche...@gmail.com>:
>>> >> > > > >> Hell Igniters,
>>> >> > > > >>
>>> >> > > > >> In this thread I would like to share and discuss some
>>> thoughts on
>>> >> > DML
>>> >> > > > >> operations' implementation, so let's start and keep it here.
>>> >> > Everyone
>>> >> > > > >> is of course welcome to share their suggestions.
>>> >> > > > >>
>>> >> > > > >> For starters, I was thinking about semantics of INSERT. In
>>> >> > traditional
>>> >> > > > >> RDBMSs, INSERT works only for records whose primary keys don't
>>> >> > > > >> conflict with those of records that are already persistent -
>>> you
>>> >> > can't
>>> >> > > > >> try to insert the same key more than once because you'll get
>>> an
>>> >> > error.
>>> >> > > > >> However, semantics of cache put is obviously different - it
>>> does
>>> >> not
>>> >> > > > >> have anything about duplicate keys, it just quietly updates
>>> values
>>> >> > in
>>> >> > > > >> case of keys' duplication. Still, cache has putIfAbsent
>>> operation
>>> >> > that
>>> >> > > > >> is closer to traditional notion of INSERT, and H2's SQL
>>> dialect
>>> >> has
>>> >> > > > >> MERGE operation which corresponds to semantics of cache put.
>>> >> Thus, I
>>> >> > > > >> suggest that we implement MERGE as a separate operation
>>> backed by
>>> >> > > > >> putIfAbsent operation, while INSERT will be implemented via
>>> put.
>>> >> > > > >>
>>> >> > > > >> And one more, probably more important thing: I suggest that we
>>> >> > create
>>> >> > > > >> separate class Update and corresponding operation update() in
>>> >> > > > >> IgniteCache. The reasons are as follows:
>>> >> > > > >>
>>> >> > > > >> - Query bears some flags that are clearly redundant for Update
>>> >> (page
>>> >> > > > >> size, locality)
>>> >> > > > >> - query() method in IgniteCache (one that accepts Query) and
>>> >> query()
>>> >> > > > >> methods in GridQueryIndexing return iterators. So, if we
>>> strive to
>>> >> > > > >> leave interfaces unchanged, we still will introduce some
>>> design
>>> >> > > > >> ugliness like query methods returning empty iterators for
>>> certain
>>> >> > > > >> queries, and/or query flags that indicate whether it's an
>>> update
>>> >> > query
>>> >> > > > >> or not, etc.
>>> >> > > > >> - If some Queries are update queries, then continuous queries
>>> >> can't
>>> >> > be
>>> >> > > > >> based on them - more design-wise ugly checks and stuff like
>>> that.
>>> >> > > > >> - I'm pretty sure there's more I don't know about.
>>> >> > > > >>
>>> >> > > > >> Comments and suggestions are welcome. Sergi Vladykin, Dmitry
>>> >> > > > >> Setrakyan, your opinions are of particular interest, please
>>> >> advise.
>>> >> > > > >>
>>> >> > > > >> Regards,
>>> >> > > > >> Alex
>>> >> > > >
>>> >> > >
>>> >> >
>>> >>
>>>
>>
>>

Reply via email to