rownum problem after migrating 5.5 causes incorrect result

Posts   
 
    
sapul
User
Posts: 49
Joined: 11-Jan-2019
# Posted on: 21-May-2019 23:42:19   

Hi Again simple_smile

We migrated our project from 2.0 with Oracle.DataAccess *ansi on (old version) to llblgen 5.5 with oracle managed drive. *ansi off (new version)

We have 2 running production sites for each, so when a BUG is reported, we have chance to compare data with the old version.

Here is one of our issues.

We run same code on the different versions.

public DataTable Fill(IPredicate filtre, long maxNumberOfItemsToReturn)
        {
            TypedListDAO dao = DAOFactory.CreateTypedListDAO();
            dao.GetMultiAsDataTable(_resultSet, resultingDataTable, maxNumberOfItemsToReturn, null, filtre, _relations, false, null, null, 0, 0);
            return resultingDataTable;
        }

please notice maxNumberOfItemsToReturn parameter that causes ROWNUM filter in the result query

in the old versiyon, there is an extra "select * from" query that wraps the original query, adding "rownum" to the external query. and every thing works as expected SELECT * FROM ( SELECT DISTINCT "YNA"."KPK_STOK_KONT_TARIHCESI"."ID" AS "StokKonteynerTarihcesiId", ..... FROM "YNA"."K...... WHERE .... AND "YNA"."DOK_KONS_EKIPMAN_YUKU"."SOC_MI" = :SocMi5)) ) WHERE rownum <= 500

but in the new version, there is no "external query" and "rownum <= 500" filter is directly added to the inner query which yields incorrect result set data. SELECT DISTINCT KPK_STOK_KONT_TARIHCESI.ID, .... FROM ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( KPK_STOK_KONT_TARIHCESI INNER JOIN ..... WHERE ( KPK_STOK_KONT_TARIHCE_KONS.KPK_KONSIMENTO_TIPI_ID = 1 AND .... AND rownum < = 500

What should I do to ensure that the number of records works correctly?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 22-May-2019 07:57:15   

Hi sapul,

Are those queries extracted directly from the tracing, or another monitor tool? Please post the exact queries, with params, etc.

Do you have any CompatibilityLevel set? (ref...). This is used to know how to use the rownum filter, although you say it's generated as rownum, so it seems it's using the default.

Also, I don't see you are using paging in that query. Could you please double check that?

David Elizondo | LLBLGen Support Team
Ayca
User
Posts: 1
Joined: 22-May-2019
# Posted on: 22-May-2019 09:24:12   

Dear Daelmo, I'm writing on behalf of sapul.

Old and new SQLs are below. simple_smile

OLD --> Returns 50 rows

SELECT * FROM (SELECT DISTINCT KPK_STOK_KONT_TARIHCESI.ID AS STOKKONTEYNERTARIHCESIID, KPK_STOK_KONT_TARIHCESI.GELIS_PUANTAJI_ONAYLI_MI AS GELISPUANTAJIONAYLIMI, KPK_STOK_KONT_TARIHCESI.GIDIS_PUANTAJI_ONAYLI_MI AS GIDISPUANTAJIONAYLIMI, KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_TARIHI AS STOGAGIRISTARIHI, KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_TARIHI AS STOKTANCIKISTARIHI, KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_LOKASYON_ID AS STOGAALINMALOKASYONUID, KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_LOKASYON_ID AS STOKTANDUSULENLOKASYONID, KPK_STOK_KONT_TARIHCESI.SON_HRKT_KODU_ID AS SONHRKTKODUID, KPK_STOK_KONT_TARIHCESI.SON_BILGI_KODU_ID AS SONBILGIKODUID, KPK_STOK_KONT_TARIHCESI.SON_GERCEK_HRKT_TARIHI AS SONHRKTTARIHI, KPK_STOK_KONT_TARIHCESI.SON_OZEL_HRKT_TARIHI AS SONOZELHRKTTARIHI, KPK_STOK_KONT_TARIHCESI.SON_KONDISYON_SINIFI_ID AS SONKONDISYONSINIFIID, KPK_STOK_KONT_TARIHCESI.HASARLI_MI AS HASARLIMI, KPK_STOK_KONT_TARIHCESI.KIRLI_MI AS KIRLIMI, KPK_STOK_KONT_TARIHCESI.SARTLI_MI AS SARTLIMI, KPK_STOK_KONT_TARIHCESI.BLOKAJLI_MI AS BLOKAJLIMI, KPK_STOK_KONT_TARIHCESI.BOOKING_ILE_ESLESMIS_MI AS BOOKINGILEESLESMISMI, KPK_STOK_KONT_TARIHCESI.ONAYLI_BOOKINGTE_MI AS ONAYLIBOOKINGTEMI, KPK_STOK_KONT_TARIHCESI.AKTARMA_TALEBI_ILE_ESLS_MI AS AKTARMATALEBIILEESLSMI, KPK_STOK_KONT_TARIHCESI.ONAYLI_AKTARMA_TALEBINDE_MI AS ONAYLIAKTARMATALEBINDEMI, KPK_STOK_KONT_TARIHCESI.FOY_BILGI_KODU_ID AS FOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.AKTARMA_FOY_BILGI_KODU_ID AS AKTARMAFOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.ITH_TASIMA_FOY_BILGI_KODU_ID AS ITHTASIMAFOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.CSC AS CSC, KPK_STOK_KONT_TARIHCESI.PAYLOAD AS PAYLOAD, KPK_STOK_KONT_TARIHCESI.HASAR_ID AS HASARID, KPK_STOK_KONT_TARIHCESI.KIRLILIK_ID AS KIRLILIKID, LPA_S3.ID AS SONHRKTKODUTIPIID, LPA_S3.AD AS SONHRKTKODUTIPIAD, LPA_S3.KOD AS SONHRKTKODUTIPIKOD, LPA_S3.RESOURCE_NAME AS SONHRKTKODUTIPIACKRESXKEY, LPA_S4.ID AS SONBILGIKODUTIPIID, LPA_S4.AD AS SONBILGIKODUTIPIAD, LPA_S4.KOD AS SONBILGIKODUTIPIKOD, LPA_S4.RESOURCE_NAME AS SONBILGIKODUTIPIACKRESXKEY, YUKLEME_EKIPMANI_ISO_KODU.ID AS YUKLEMEEKIPMANIISOKODUID, YUKLEME_EKIPMANI_ISO_KODU.AD AS YUKLEMEEKIPMANIISOKODUAD, YUKLEME_EKIPMANI_ISO_KODU.ISO_KOD AS YUKLEMEEKIPMANIISOKODU, YUKLEME_EKIPMANI_ISO_KODU.UST_YUK_EKIPMANI_ISO_KODU_ID AS USTYUKEKIPMANIISOKODUID, YUKLEME_EKIPMANI_TIPI.ID AS YUKLEMEEKIPMANITIPID, YUKLEME_EKIPMANI_TIPI.KOD AS YUKLEMEEKIPMANITIPIKOD, YUKLEME_EKIPMANI_TIPI.TURKCE_AD AS YUKLEMEEKIPMANITIPIAD, YUKLEME_EKIPMANI_BOYUTU.ID AS YUKLEMEEKIPMANIBOYUTID, YUKLEME_EKIPMANI_BOYUTU.KOD AS YUKLEMEEKIPMANIBOYUTKOD, YUKLEME_EKIPMANI_BOYUTU.TURKCE_AD AS YUKLEMEEKIPMANIBOYUTAD, DOK_EKIPMAN.ID AS DOKKONTEYNERID, DOK_EKIPMAN.PREFIX AS DOKKONTEYNERPREFIX, DOK_EKIPMAN.NUMARA AS DOKKONTEYNERNUMARA, DOK_EKIPMAN.OZEL_EKIPMAN_NO AS DOKKONTEYNEROZELNUMARA, DOK_EKIPMAN.YERLI_MI AS DOKKONTEYNERYERLIMI, LPA_S1.ID AS SONROTASYONID, LPA_S1.KOD AS SONROTASYONKOD, LPA_S1.TANIM AS SONROTASYONTANIM, LPA_S2.ID AS SONSTOKDURUMKODUID, LPA_S2.KOD AS SONSTOKDURUMKODUKOD, LPA_S2.ACIKLAMA AS SONSTOKDURUMKODUACIKLAMA, LPA_S2.RESOURCE_NAME AS SONSTOKDURUMKODURESXKEY, LPA_S5.ID AS SONTASIMAARACIID, LPA_S5.AD AS SONTASIMAARACIAD, LPA_S5.ACIKLAMA AS SONTASIMAARACIACIKLAMA, LPA_S5.TASIMA_YONTEMI_ID AS SONTASIMAARACITASIMAYNTMID, LPA_S5.RESOURCE_NAME AS SONTASIMAARACIRESXKEY, LPA_S6.ID AS SONHRKTBASLOKASYONID, LPA_S6.KOD AS SONHRKTBASLOKASYONKOD, LPA_S6.AD AS SONHRKTBASLOKASYONAD, LPA_S6.LOKASYON_TIPI_ID AS SONHRKTBASLOKASYONTIPID, LPA_S7.ID AS SONHRKTBITLOKASYONID, LPA_S7.KOD AS SONHRKTBITLOKASYONKOD, LPA_S7.AD AS SONHRKTBITLOKASYONAD, LPA_S7.LOKASYON_TIPI_ID AS SONHRKTBITLOKASYONTIPID, LPA_S8.ID AS STOGAGIRISLOKASYONID, LPA_S8.KOD AS STOGAGIRISLOKASYONKOD, LPA_S8.AD AS STOGAGIRISLOKASYONAD, LPA_S8.LOKASYON_TIPI_ID AS STOGAGIRISLOKASYONTIPID, LPA_S9.ID AS STOKTANCIKISLOKASYONID, LPA_S9.KOD AS STOKTANCIKISLOKASYONKOD, LPA_S9.AD AS STOKTANCIKISLOKASYONAD, LPA_S9.LOKASYON_TIPI_ID AS STOKTANCIKISLOKASYONTIPID, KPK_STOK_KONT_TARIHCESI.KPK_KUMPANYA_ID AS DOKKUMPANYAID, KPK_STOK_KONT_TARIHCESI.BKG_BOOKING_TIPI_ID AS BKGBOOKINGTIPIID, KPK_STOK_KONT_TARIHCESI.BKG_YUKLEME_TIPI_ID AS BKGYUKLEMETIPIID, KPK_STOK_KONT_TARIHCESI.SON_BIT_LOK_STK_BOLGE_ID AS SONBITLOKSTKBOLGEID FROM KPK_STOK_KONT_TARIHCESI, KPK_STOK_KONT_TARIHCE_KONS, DOK_KONS_EKIPMAN_YUKU, KPK_ROTASYON LPA_S1, KPK_STOK_DURUM_KODU LPA_S2, DOK_EKIPMAN, YUKLEME_EKP_TARIHCE_KODU LPA_S3, YUKLEME_EKP_TARIHCE_KODU LPA_S4, TASIMA_ARACI LPA_S5, YUKLEME_EKIPMANI_ISO_KODU, YUKLEME_EKIPMANI_BOYUTU, YUKLEME_EKIPMANI_TIPI, LOKASYON LPA_S6, LOKASYON LPA_S7, LOKASYON LPA_S8, LOKASYON LPA_S9, KPK_STOK_BOLGE_LOKASYON, KPK_STK_BLG_LOK_KULLANICI, KPK_STOK_BOLGE WHERE KPK_STOK_KONT_TARIHCESI.ID = KPK_STOK_KONT_TARIHCE_KONS.KPK_STOK_KONT_TARIHCESI_ID AND DOK_KONS_EKIPMAN_YUKU.ID = KPK_STOK_KONT_TARIHCE_KONS.DOK_KONS_EKIPMAN_YUKU_ID AND LPA_S1.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_ROTASYON_ID AND LPA_S2.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_STOK_DURUM_KODU_ID AND DOK_EKIPMAN.ID = KPK_STOK_KONT_TARIHCESI.DOK_EKIPMAN_ID AND LPA_S3.ID = KPK_STOK_KONT_TARIHCESI.SON_HRKT_KODU_TIPI_ID AND LPA_S4.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_BILGI_KODU_TIPI_ID AND LPA_S5.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_TASIMA_ARACI_ID AND YUKLEME_EKIPMANI_ISO_KODU.ID = DOK_EKIPMAN.YUKLEME_EKIPMANI_ISO_KODU_ID AND YUKLEME_EKIPMANI_BOYUTU.ID = YUKLEME_EKIPMANI_ISO_KODU.YUKLEME_EKIPMANI_BOYUTU_ID AND YUKLEME_EKIPMANI_TIPI.ID = YUKLEME_EKIPMANI_ISO_KODU.YUKLEME_EKIPMANI_TIPI_ID AND LPA_S6.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_HRKT_BAS_LOKASYON_ID AND LPA_S7.ID(+) = KPK_STOK_KONT_TARIHCESI.SON_HRKT_BIT_LOKASYON_ID AND LPA_S8.ID(+) = KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_LOKASYON_ID AND LPA_S9.ID(+) = KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_LOKASYON_ID AND KPK_STOK_KONT_TARIHCESI.SON_HRKT_BIT_LOKASYON_ID = KPK_STOK_BOLGE_LOKASYON.LOKASYON_ID(+) AND KPK_STOK_BOLGE_LOKASYON.ID = KPK_STK_BLG_LOK_KULLANICI.STOK_BOLGE_LOK_ID(+) AND KPK_STOK_BOLGE.ID(+) = KPK_STOK_BOLGE_LOKASYON.KPK_STOK_BOLGE_ID AND ( ( KPK_STOK_KONT_TARIHCE_KONS.KPK_KONSIMENTO_TIPI_ID = 1 AND KPK_STOK_KONT_TARIHCESI.PAYLOAD IS NULL AND KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_TARIHI IS NULL AND ( KPK_STOK_KONT_TARIHCESI.KPK_KUMPANYA_ID = 1 AND DOK_KONS_EKIPMAN_YUKU.ALT_KUMPANYA_ID IS NULL AND DOK_KONS_EKIPMAN_YUKU.SOC_MI = 0) AND ( KPK_STOK_KONT_TARIHCESI.SON_STOK_DURUM_KODU_ID = 2 AND KPK_STOK_KONT_TARIHCESI.SON_HRKT_BAS_LOKASYON_ID = 62334)))) WHERE ROWNUM <= 500

NEW --> Returns 2 rows

SELECT DISTINCT KPK_STOK_KONT_TARIHCESI.ID AS STOKKONTEYNERTARIHCESIID, KPK_STOK_KONT_TARIHCESI.GELIS_PUANTAJI_ONAYLI_MI AS GELISPUANTAJIONAYLIMI, KPK_STOK_KONT_TARIHCESI.GIDIS_PUANTAJI_ONAYLI_MI AS GIDISPUANTAJIONAYLIMI, KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_TARIHI AS STOGAGIRISTARIHI, KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_TARIHI AS STOKTANCIKISTARIHI, KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_LOKASYON_ID AS STOGAALINMALOKASYONUID, KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_LOKASYON_ID AS STOKTANDUSULENLOKASYONID, KPK_STOK_KONT_TARIHCESI.SON_HRKT_KODU_ID AS SONHRKTKODUID, KPK_STOK_KONT_TARIHCESI.SON_BILGI_KODU_ID AS SONBILGIKODUID, KPK_STOK_KONT_TARIHCESI.SON_GERCEK_HRKT_TARIHI AS SONHRKTTARIHI, KPK_STOK_KONT_TARIHCESI.SON_OZEL_HRKT_TARIHI AS SONOZELHRKTTARIHI, KPK_STOK_KONT_TARIHCESI.SON_KONDISYON_SINIFI_ID AS SONKONDISYONSINIFIID, KPK_STOK_KONT_TARIHCESI.HASARLI_MI AS HASARLIMI, KPK_STOK_KONT_TARIHCESI.KIRLI_MI AS KIRLIMI, KPK_STOK_KONT_TARIHCESI.SARTLI_MI AS SARTLIMI, KPK_STOK_KONT_TARIHCESI.BLOKAJLI_MI AS BLOKAJLIMI, KPK_STOK_KONT_TARIHCESI.BOOKING_ILE_ESLESMIS_MI AS BOOKINGILEESLESMISMI, KPK_STOK_KONT_TARIHCESI.ONAYLI_BOOKINGTE_MI AS ONAYLIBOOKINGTEMI, KPK_STOK_KONT_TARIHCESI.AKTARMA_TALEBI_ILE_ESLS_MI AS AKTARMATALEBIILEESLSMI, KPK_STOK_KONT_TARIHCESI.ONAYLI_AKTARMA_TALEBINDE_MI AS ONAYLIAKTARMATALEBINDEMI, KPK_STOK_KONT_TARIHCESI.FOY_BILGI_KODU_ID AS FOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.AKTARMA_FOY_BILGI_KODU_ID AS AKTARMAFOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.ITH_TASIMA_FOY_BILGI_KODU_ID AS ITHTASIMAFOYBILGIKODUID, KPK_STOK_KONT_TARIHCESI.CSC AS CSC, KPK_STOK_KONT_TARIHCESI.PAYLOAD AS PAYLOAD, KPK_STOK_KONT_TARIHCESI.HASAR_ID AS HASARID, KPK_STOK_KONT_TARIHCESI.KIRLILIK_ID AS KIRLILIKID, LPA_S3.ID AS SONHRKTKODUTIPIID, LPA_S3.AD AS SONHRKTKODUTIPIAD, LPA_S3.KOD AS SONHRKTKODUTIPIKOD, LPA_S3.RESOURCE_NAME AS SONHRKTKODUTIPIACKRESXKEY, LPA_S4.ID AS SONBILGIKODUTIPIID, LPA_S4.AD AS SONBILGIKODUTIPIAD, LPA_S4.KOD AS SONBILGIKODUTIPIKOD, LPA_S4.RESOURCE_NAME AS SONBILGIKODUTIPIACKRESXKEY, YUKLEME_EKIPMANI_ISO_KODU.ID AS YUKLEMEEKIPMANIISOKODUID, YUKLEME_EKIPMANI_ISO_KODU.AD AS YUKLEMEEKIPMANIISOKODUAD, YUKLEME_EKIPMANI_ISO_KODU.ISO_KOD AS YUKLEMEEKIPMANIISOKODU, YUKLEME_EKIPMANI_ISO_KODU.UST_YUK_EKIPMANI_ISO_KODU_ID AS USTYUKEKIPMANIISOKODUID, YUKLEME_EKIPMANI_TIPI.ID AS YUKLEMEEKIPMANITIPID, YUKLEME_EKIPMANI_TIPI.KOD AS YUKLEMEEKIPMANITIPIKOD, YUKLEME_EKIPMANI_TIPI.TURKCE_AD AS YUKLEMEEKIPMANITIPIAD, YUKLEME_EKIPMANI_BOYUTU.ID AS YUKLEMEEKIPMANIBOYUTID, YUKLEME_EKIPMANI_BOYUTU.KOD AS YUKLEMEEKIPMANIBOYUTKOD, YUKLEME_EKIPMANI_BOYUTU.TURKCE_AD AS YUKLEMEEKIPMANIBOYUTAD, DOK_EKIPMAN.ID AS DOKKONTEYNERID, DOK_EKIPMAN.PREFIX AS DOKKONTEYNERPREFIX, DOK_EKIPMAN.NUMARA AS DOKKONTEYNERNUMARA, DOK_EKIPMAN.OZEL_EKIPMAN_NO AS DOKKONTEYNEROZELNUMARA, DOK_EKIPMAN.YERLI_MI AS DOKKONTEYNERYERLIMI, LPA_S1.ID AS SONROTASYONID, LPA_S1.KOD AS SONROTASYONKOD, LPA_S1.TANIM AS SONROTASYONTANIM, LPA_S2.ID AS SONSTOKDURUMKODUID, LPA_S2.KOD AS SONSTOKDURUMKODUKOD, LPA_S2.ACIKLAMA AS SONSTOKDURUMKODUACIKLAMA, LPA_S2.RESOURCE_NAME AS SONSTOKDURUMKODURESXKEY, LPA_S5.ID AS SONTASIMAARACIID, LPA_S5.AD AS SONTASIMAARACIAD, LPA_S5.ACIKLAMA AS SONTASIMAARACIACIKLAMA, LPA_S5.TASIMA_YONTEMI_ID AS SONTASIMAARACITASIMAYNTMID, LPA_S5.RESOURCE_NAME AS SONTASIMAARACIRESXKEY, LPA_S6.ID AS SONHRKTBASLOKASYONID, LPA_S6.KOD AS SONHRKTBASLOKASYONKOD, LPA_S6.AD AS SONHRKTBASLOKASYONAD, LPA_S6.LOKASYON_TIPI_ID AS SONHRKTBASLOKASYONTIPID, LPA_S7.ID AS SONHRKTBITLOKASYONID, LPA_S7.KOD AS SONHRKTBITLOKASYONKOD, LPA_S7.AD AS SONHRKTBITLOKASYONAD, LPA_S7.LOKASYON_TIPI_ID AS SONHRKTBITLOKASYONTIPID, LPA_S8.ID AS STOGAGIRISLOKASYONID, LPA_S8.KOD AS STOGAGIRISLOKASYONKOD, LPA_S8.AD AS STOGAGIRISLOKASYONAD, LPA_S8.LOKASYON_TIPI_ID AS STOGAGIRISLOKASYONTIPID, LPA_S9.ID AS STOKTANCIKISLOKASYONID, LPA_S9.KOD AS STOKTANCIKISLOKASYONKOD, LPA_S9.AD AS STOKTANCIKISLOKASYONAD, LPA_S9.LOKASYON_TIPI_ID AS STOKTANCIKISLOKASYONTIPID, KPK_STOK_KONT_TARIHCESI.KPK_KUMPANYA_ID AS DOKKUMPANYAID, KPK_STOK_KONT_TARIHCESI.BKG_BOOKING_TIPI_ID AS BKGBOOKINGTIPIID, KPK_STOK_KONT_TARIHCESI.BKG_YUKLEME_TIPI_ID AS BKGYUKLEMETIPIID, KPK_STOK_KONT_TARIHCESI.SON_BIT_LOK_STK_BOLGE_ID AS SONBITLOKSTKBOLGEID FROM ((((((((((((((((((KPK_STOK_KONT_TARIHCESI INNER JOIN KPK_STOK_KONT_TARIHCE_KONS ON KPK_STOK_KONT_TARIHCESI.ID = KPK_STOK_KONT_TARIHCE_KONS.KPK_STOK_KONT_TARIHCESI_ID) INNER JOIN DOK_KONS_EKIPMAN_YUKU ON DOK_KONS_EKIPMAN_YUKU.ID = KPK_STOK_KONT_TARIHCE_KONS.DOK_KONS_EKIPMAN_YUKU_ID) LEFT JOIN KPK_ROTASYON LPA_S1 ON LPA_S1.ID = KPK_STOK_KONT_TARIHCESI.SON_ROTASYON_ID) LEFT JOIN KPK_STOK_DURUM_KODU LPA_S2 ON LPA_S2.ID = KPK_STOK_KONT_TARIHCESI.SON_STOK_DURUM_KODU_ID) INNER JOIN DOK_EKIPMAN ON DOK_EKIPMAN.ID = KPK_STOK_KONT_TARIHCESI.DOK_EKIPMAN_ID) INNER JOIN YUKLEME_EKP_TARIHCE_KODU LPA_S3 ON LPA_S3.ID = KPK_STOK_KONT_TARIHCESI.SON_HRKT_KODU_TIPI_ID) LEFT JOIN YUKLEME_EKP_TARIHCE_KODU LPA_S4 ON LPA_S4.ID = KPK_STOK_KONT_TARIHCESI.SON_BILGI_KODU_TIPI_ID) LEFT JOIN TASIMA_ARACI LPA_S5 ON LPA_S5.ID = KPK_STOK_KONT_TARIHCESI.SON_TASIMA_ARACI_ID) INNER JOIN YUKLEME_EKIPMANI_ISO_KODU ON YUKLEME_EKIPMANI_ISO_KODU.ID = DOK_EKIPMAN.YUKLEME_EKIPMANI_ISO_KODU_ID) INNER JOIN YUKLEME_EKIPMANI_BOYUTU ON YUKLEME_EKIPMANI_BOYUTU.ID = YUKLEME_EKIPMANI_ISO_KODU.YUKLEME_EKIPMANI_BOYUTU_ID) INNER JOIN YUKLEME_EKIPMANI_TIPI ON YUKLEME_EKIPMANI_TIPI.ID = YUKLEME_EKIPMANI_ISO_KODU.YUKLEME_EKIPMANI_TIPI_ID) LEFT JOIN LOKASYON LPA_S6 ON LPA_S6.ID = KPK_STOK_KONT_TARIHCESI.SON_HRKT_BAS_LOKASYON_ID) LEFT JOIN LOKASYON LPA_S7 ON LPA_S7.ID = KPK_STOK_KONT_TARIHCESI.SON_HRKT_BIT_LOKASYON_ID) LEFT JOIN LOKASYON LPA_S8 ON LPA_S8.ID = KPK_STOK_KONT_TARIHCESI.STOGA_GIRIS_LOKASYON_ID) LEFT JOIN LOKASYON LPA_S9 ON LPA_S9.ID = KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_LOKASYON_ID) LEFT JOIN KPK_STOK_BOLGE_LOKASYON ON KPK_STOK_KONT_TARIHCESI.SON_HRKT_BIT_LOKASYON_ID = KPK_STOK_BOLGE_LOKASYON.LOKASYON_ID) LEFT JOIN KPK_STK_BLG_LOK_KULLANICI ON KPK_STOK_BOLGE_LOKASYON.ID = KPK_STK_BLG_LOK_KULLANICI.STOK_BOLGE_LOK_ID) LEFT JOIN KPK_STOK_BOLGE ON KPK_STOK_BOLGE.ID = KPK_STOK_BOLGE_LOKASYON.KPK_STOK_BOLGE_ID) WHERE ( KPK_STOK_KONT_TARIHCE_KONS.KPK_KONSIMENTO_TIPI_ID = 1 AND KPK_STOK_KONT_TARIHCESI.PAYLOAD IS NULL AND KPK_STOK_KONT_TARIHCESI.STOKTAN_CIKIS_TARIHI IS NULL AND ( KPK_STOK_KONT_TARIHCESI.KPK_KUMPANYA_ID = 1 AND DOK_KONS_EKIPMAN_YUKU.ALT_KUMPANYA_ID IS NULL AND DOK_KONS_EKIPMAN_YUKU.SOC_MI = 0) AND ( KPK_STOK_KONT_TARIHCESI.SON_STOK_DURUM_KODU_ID = 2 AND KPK_STOK_KONT_TARIHCESI.SON_HRKT_BAS_LOKASYON_ID = 62334)) AND ROWNUM <= 500

sustundag
User
Posts: 3
Joined: 22-May-2019
# Posted on: 22-May-2019 15:08:09   

Dear Daelmo,

I compared LLBLGen v2.0 Oracle DQE and v5.5 DQE.

v2.0 Code. DynamicQueryEngine class.


if(maxNumberOfItemsToReturn > 0)
            {
                // only emit the rowlimit SQL if DISTINCT is emitted as well or when there are no relations specified or when the limit is 1,
                // as a limit of 1 isn't selecting duplicates otherwise set the flag in the RetrievalQuery object for manual limitation.
                if(distinctEmitted || !relationsSpecified || (maxNumberOfItemsToReturn==1))
                {
                    // embed the complete query in a select * with rownum limiter
                    queryAsString = String.Format("SELECT * FROM ({0}) WHERE rownum <= {1}", queryText.ToString(), maxNumberOfItemsToReturn);
                }
                else
                {
                    selectQuery.RequiresClientSideLimitation=true;
                    selectQuery.MaxNumberOfItemsToReturnClientSide = maxNumberOfItemsToReturn;
                    queryAsString = queryText.ToString();
                }
            }
            else
            {
                queryAsString = queryText.ToString();
            }

v5.5 Code. DynamicQueryEngine class.


if(parameters.RowsToTake > 0)
            {
                // row limits are emitted always, unless duplicates are required but DISTINCT wasn't emitable. If not emitable, switch to client-side row limitation
                if(distinctEmitted || !resultsCouldContainDuplicates || parameters.GroupBySpecified || parameters.AllowDuplicates)
                {
                    bool aggregateFunctionInSelect = false;
                    foreach(IEntityFieldCore field in selectList)
                    {
                        aggregateFunctionInSelect |= field.AggregateFunctionToApply != AggregateFunction.None;
                    }
                    if(aggregateFunctionInSelect || parameters.GroupBySpecified || parameters.SortClauseSpecified)
                    {
                        // we can't append a simple rownum <= number predicate, as that would influence the aggregates, groupby or orderby clause
                        // as these have to be applied on the full set and the rownum on the resulting set. So we've to flag the
                        // code that it has to wrap the query generated instead.
                        wrapInRowNumLimitationQuery = true;
                    }
                    else
                    {
                        fragments.AddFragments(whereClauseEmitted ? "AND" : "WHERE", "rownum <= ", parameters.RowsToTake);
                    }
                }
                else
                {
                    toReturn.RequiresClientSideLimitation = true;
                    toReturn.ManualRowsToTake = parameters.RowsToTake;
                }
            }
            AppendGroupByClause(parameters.GroupByToUse, fragments, toReturn);
            AppendUnionedQueries(parameters.UnionedQueries, fragments, toReturn);
            AppendOrderByClause(parameters.SorterToUse, fragments, toReturn);
            string queryText = fragments.ToString();
            if(wrapInRowNumLimitationQuery)
            {
                queryText = "SELECT * FROM (" + queryText + ") WHERE rownum <= " + parameters.RowsToTake;
            }

Because of If block (below), wrapInRowNumLimitationQuery property is always false in our sample. if(aggregateFunctionInSelect || parameters.GroupBySpecified || parameters.SortClauseSpecified)

But in v2.0, distinctEmitted property was sufficient for wrapping query.

I think that this is a breaking change or a bug for v5.5

urgently waiting for your reply

Thanks

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 23-May-2019 04:24:45   

You need to use a sortClause, otherwise the resultset won't be predictable with a limit.

sustundag
User
Posts: 3
Joined: 22-May-2019
# Posted on: 23-May-2019 07:04:05   

Hi Walaa,

Ok, adding a sorter solves the problem but i think it is a workaround. I wonder why distinctemitted propery has been excluded from IF statement. Is there a special reason which causes a bug?


        if(aggregateFunctionInSelect || parameters.GroupBySpecified || parameters.SortClauseSpecified)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 23-May-2019 10:59:55   

It's right there in the comments: if a sort clause is specified we need to wrap it in a rownum query, otherwise we'll append the rownum clause.

Taking a limited number of rows from a resultset without a sortclause is something that's useless anyway: you don't know which rows you get, it'll be random.

Frans Bouma | Lead developer LLBLGen Pro
sustundag
User
Posts: 3
Joined: 22-May-2019
# Posted on: 23-May-2019 12:48:21   

Hi Otis, Ok, I understand sorter and rownum relation.

But I need to have answer for the question below; How should I develop my code if I want to get the top 500 records from an select distinct query which doesn't have a sorter?

Thanks

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 23-May-2019 16:27:04   

sustundag wrote:

Hi Otis, Ok, I understand sorter and rownum relation.

But I need to have answer for the question below; How should I develop my code if I want to get the top 500 records from an select distinct query which doesn't have a sorter?

Thanks

You should always specify a sorter when doing a TOP n query. It otherwise makes little sense. Our code allows these kind of queries but really in practice they don't make much sense.

The code we have in the DQE more or less assumes a sorter is specified in the case of a limit/take is specified, our tests do too. I think it goes wrong in your case because there is an existing where clause with (+) non-ansi join clauses, so the 'and' with the rownum fails in that case as the rownum... on which row is that applied... not clear.

If I do a simple select with a take in linq:

var metaData = new LinqMetaData(adapter);
var q = (from e in metaData.Emp
              select e).Take(3);

It gives:


SELECT "LPA_L1"."COMM"   AS "Comm",
       "LPA_L1"."DEPTNO"   AS "Deptno",
       "LPA_L1"."EMPNO" AS "Empno",
       "LPA_L1"."ENAME" AS "Ename",
       "LPA_L1"."HIREDATE" AS "Hiredate",
       "LPA_L1"."JOB"     AS "Job",
       "LPA_L1"."MGR"     AS "Mgr",
       "LPA_L1"."SAL"     AS "Sal"
FROM   "SCOTT"."EMP" "LPA_L1"
WHERE  rownum <= 3 

which works (but makes no sense at all either).

the change was made back in 2008 for v2.6. As the lack of a sorter in this scenario is useless, it hid the presence of this issue till now, 11 years later! simple_smile

Not sure we should fix this though, as the resultset is wrong no matter what: the sorter is essential.

Frans Bouma | Lead developer LLBLGen Pro