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
>  

Reply via email to