Workaround:
Changed mapping from LONGVARBINARY to  BINARY 
(DefaultSelectTranslator#isUnsupportedForDistinct does not catch this type as 
unsupported).

Atte. Juan Manuel Díaz Lara 

    On Wednesday, November 29, 2017, 9:15:27 AM CST, Nikita Timofeev 
<ntimof...@objectstyle.com> wrote:  
 
 Answered at dev@ list, but leave a note here too.
Looks like a bug to me too. Will investigate and file a bug (and
ideally make a fix) if required.

On Wed, Nov 29, 2017 at 9:17 AM, Juan Manuel Diaz Lara
<jmdia...@yahoo.com.invalid> wrote:
> I created a new project, with entities Products -toMany-> 
> StockcurrentCorporativo, with same results.
> Tracing code, I arrived to DefaultSelectTranslator#isUnsupportedForDistinct, 
> this is the cause for cayenne not including a DISTINCT in generated SQL, 
> because I have columns mapping to types "not supported for distinct clause". 
> But I found a note on method DefaultSelectTranslator#isSuppressingDistinct 
> that tell that cayenne should should do an in-memory  distinct operation. so 
> this is not working well (a bug ?).
> At least I conclude that:
> 1. Cayenne is deciding with types of columns can be used for DISTINCT, but 
> this is not generally true, some db's ignore not sortable columns when used 
> in DISTINCT queries. Maybe this decision should be delegated to the specific 
> db translator.
>
> 2. There is a bug because cayenne must perform the in-memory distinct when 
> suppressing DISTINCT in generated SQL.
> I removed my longvarbinary columns and the problem gone, a DISTINCT SQL was 
> generated, confirming the previous conclusions.
> Well, this was a try, in reality, I can not simply remove my longvarbinary 
> columns.
> Does some body can report this as a bug ?.
> Thanks.
>
>
> Atte. Juan Manuel Díaz Lara
>
>    On Tuesday, November 28, 2017, 2:04:43 PM CST, Juan Manuel Diaz Lara 
><jmdia...@yahoo.com.INVALID> wrote:
>
>  I am agree that this kind of query should generate a SQL DISTINCT, but the 
>fact is that adding a joint()brings only one product on result even the sql 
>generates 16 rows, so Cayenne is doing some kind of IN-MEMORY DISTINCT that is 
>not done without a joint(), maybe a bug because there are two different 
>executions paths.
> I will create a new mapping with only this two tables to recheck is not a 
> problem of model or any other mistake. I'll report results.
> thanks.
>
> Atte. Juan Manuel Díaz Lara
>
>    On Tuesday, November 28, 2017, 11:42:14 AM CST, Lon Varscsak 
><lon.varsc...@gmail.com> wrote:
>
>  I think the part that's missing is a "distinct".  I'm assuming there are 4
> stockcurrent_corporativo rows for that one product, but if it had a
> distinct it would be showing one.  I don't think that
> ObjectSelect/FluentSelect have the ability to turn on/off distinct, but for
> me, this always generates a "distinct" in the query.  I'm not sure why it
> would be different for you.
>
> -Lon
>
> On Mon, Nov 27, 2017 at 8:45 PM, Juan Manuel Diaz Lara <
> jmdia...@yahoo.com.invalid> wrote:
>
>> More details, this code should return only one product entity, but
>> produces a result list with 4 items, all items being the same product
>> entity (the purpose is get products which have stock in at leas one
>> location):
>>
>>
>> ObjectSelect<Product> q = ObjectSelect.query(Product.class)
>> .where(Product.EXISTENCIAS_CORPORATIVAS.dot(StockCurrentCorporativo.UNITS).gt(0.0))
>> .and(Product.CODE.like("USBVGA");List<Product> results =
>> q.select(context);
>>
>> (this is could be expressed in plain SQL as a correlated query inside an
>> EXISTS operation over table StockCurrentCorporativo)
>> Generates :
>>
>> SELECT <<all columns from t0 table>>
>> FROM public.products t0 JOIN public.stockcurrent_corporativo t1 ON (t0.id
>> = t1.product) WHERE (t1.units > ?) AND (t0.code LIKE ?)    ORDER BY
>> t0.name [bind: 1->units:0.0, 2->code:'USBVGA']
>>
>> This produces 4 identical rows form database that end up on only one
>> product entity but repeated 4 times on results list (results.size() = 4).
>> Changig the query to
>>
>> ObjectSelect<Product> q = ObjectSelect.query(Product.class)
>> .where(Product.EXISTENCIAS_CORPORATIVAS.dot(StockCurrentCorporativo.UNITS).gt(0.0))
>> .and(Product.CODE.like("USBVGA");q.prefetch(Product.
>> EXISTENCIAS_CORPORATIVAS.joint()); // <-- change
>> List<Product> results = q.select(context);
>>
>>
>> produces this SQL:
>>
>> SELECT <<all columns from t0 table>> FROM public.products t0 LEFT JOIN
>> public.stockcurrent_corporativo t1 ON (t0.id = t1.product) JOIN
>> public.stockcurrent_corporativo t2 ON (t0.id = t2.product) WHERE
>> (t2.units > ?) AND (t0.code LIKE ?) ORDER BY t0.name [bind: 1->units:0.0,
>> 2->code:'USBVGA']
>>
>>
>> note that the two references to the relationship traslate to two joins.
>> This SQL query produces 16 identical rows!!, that end up in only one
>> product entity, but surprisingly, results list have only one item
>> (product), and this is what is expected !!.
>> All this is annoying, or maybe I am not understanding well the query rules
>> of cayenne.
>> Yes, I can make the query with SQLTemplate, but would like to use only
>> object oriented queries. Could it be done ? In general. how to include
>> conditions over the many size of relationships ?.
>> Please help.
>>
>> Atte. Juan Manuel Díaz Lara
>>
>>    On Sunday, November 26, 2017, 8:57:50 PM CST, Juan Manuel Diaz Lara
>> <jmdia...@yahoo.com.INVALID> wrote:
>>
>>  I am using 4.0.M5, previously this query worked as I expected:
>>
>>                  ObjectSelect<Product> q = ObjectSelect.query(Product.class)
>>              .where(Product.EXISTENCIAS_CORPORATIVAS.dot(
>> StockCurrentCorporativo.UNITS).gt(0.0))
>> .and(Product.CODE.like("USBVGA");
>>                List<Product> results = q.select(context);
>>
>> The objective is to get products for which we have stock in any location,
>> StockCurrentCorporativo has the stock by location.
>> I restricted the example query to just one specific product and expect to
>> get only one product in results, but got results.size() > 1, with all items
>> being the same product (the same object on my tests).
>>
>> The generated SQL from the log is:
>>    SELECT <<all columns from t0 table>>
>>    FROM public.products t0 JOIN public.stockcurrent_corporativo t1 ON (
>> t0.id = t1.product) WHERE (t1.units > ?) AND (t0.code LIKE ?)    ORDER
>> BY t0.name [bind: 1->units:0.0, 2->code:'USBVGA']
>>
>>
>> EXISTENCIAS_CORPORATIVAS is a toMany relationship from Product and have
>> type StockCurrentCorporativo, defined in _Product as :
>>
>>      public static final Property<List<StockCurrentCorporativo>>
>> EXISTENCIAS_CORPORATIVAS = Property.create("existenciasCorporativas",
>> List.class);
>>
>>
>>  To be fair, I do not know when this started, the production app is
>> working well, this is on a my development environment when I started to
>> work for a new requirement.
>> I reviewed the mapping and it looks ok, any help will be appreciated.
>>
>> Atte. Juan Manuel Díaz Lara
>>



-- 
Best regards,
Nikita Timofeev  

Reply via email to