--
-- ### Checking master predicate handling optimized from version 2.52.20
-- 

drop if exists procedure tsnow;
@
create procedure tsnow() return datetime
begin
  return sysdate;
end;
@

drop if exists procedure randDate;
@
create procedure randDate() return datetime
begin
    var backsec int = randint(10000000);
    return long2date(date2long(sysdate) - :backsec + 5000000);
end;
@

drop if exists procedure fillCompany;
@
create procedure fillCompany(startcp in int, endcp in int)
begin
  var i int = :startcp;
  while :i < :endcp
  begin
      insert into company ( cpid, cpname, debnr, gpid )
          values ( :i, 'CP-' | randint(1000), :i, 1);
      :i = :i+1;
  end;
end;
@

drop if exists procedure fillInvoice;
@
create procedure fillInvoice(startinv in int, endinv in int, status in string(20), cpid in int)
begin
  var i int = :startinv;
  while :i < :endinv
  begin
      insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid )
          values ( :i, 'RE-' | :i, randDate(), :status, 19, :cpid);
      :i = :i+1;
  end;
end;
@

drop if exists procedure fillPosRule;
@
create procedure fillPosRule(startrule in int, endrule in int, cpid in int)
begin
  var i int = :startrule;
  while :i < :endrule
  begin
      insert into posrule ( prid, startbook, endbook, booking, cpid )
          values ( :i, randDate(), randDate(), 'sample book', :cpid);
      :i = :i+1;
  end;
end;
@


drop if exists table company;
create table company ( primary cpid int not null, cpname string(20), debnr int, gpid int);
create btree company_b1 on company(cpname);

drop if exists table posrule;
create table posrule(prid int not null,
       startbook datetime not null,
       endbook datetime not null,
       booking string(20) not null,
       cpid int not null);

drop if exists table invoice;
create table invoice(invid int not null,
       invnr string(20) not null,
       invdate datetime not null,
       invstatus string(20) not null,
       taxquote int not null,
       cpid int not null);

create primary btree on invoice(invid);


call fillPosRule(1, 20, 1);
call fillPosRule(20, 30, 2);
call fillPosRule(30, 50, 3);

call fillInvoice(1, 100, 'EDIT' , 1);
call fillInvoice(100, 200, 'BOOKED' , 2);
call fillInvoice(200, 300, 'PAYED' , 3);


call fillCompany(1, 300);


drop if exists table debitor;
create table debitor(debnr int not null,
       debname string(20) not null);

drop if exists table companygroup;
create table companygroup ( gpid int, gpname string(20));


insert into companygroup values ( 1, 'Group A');
insert into companygroup values ( 2, 'Group B');
insert into companygroup values ( 3, 'Group C');



-- insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 1, 'RE-4711', '01.07.2025', 'BOOKED', 19, 1);
-- insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 2, 'RE-4712', '14.07.2025', 'REMIND', 19, 2);
-- insert into invoice ( invid, invnr, invdate, invstatus, taxquote, cpid ) values ( 3, 'RE-4713', '14.07.2025', 'EDIT', 19, 3);

insert into debitor values ( 4711, 'Deb1');
insert into debitor values ( 4712, 'Deb2');
insert into debitor values ( 4713, 'Deb3');


-- we need at least two inner joins to verify table alias handling
drop if exists view companyview;
create view companyview as
select
    cp.cpid as cpid,
    cp.cpname as cpname,
    deb.debname as debname,
    gp.gpname as gpname
from company cp
inner join debitor deb on cp.debnr = deb.debnr
inner join companygroup gp on gp.gpid = cp.gpid;

drop if exists view invoiceview;
create view invoiceview as
select
    inv.invid as invid,
    inv.invnr as invnr,
    inv.invdate as invdate,
    inv.taxquote as taxquote,
    inv.invstatus as invstatus,
    inv.cpid as cpid,
    cp.cpname as cpname,
    cp.cpname | deb.debname as cpdeb
from invoice inv
inner join company cp on inv.cpid = cp.cpid
inner join debitor deb on cp.debnr = deb.debnr;



----------------
-- Join Cases --
----------------

-- Case A : master condition on plain table with full table scan
plan select cpid from company where cpname = 'Limited' or cpname = 'Walter GmbH';

-- Case B : Full index trace via in condition
plan select cpid from company where cpname in ( 'Limited', 'Walter GmbH');


-- Case C : master condition, which can be evaluated on inner join level inside the companyview 
plan select cpid, debname from companyview where lower(cpname) like '%Lim%' or debname = 'Deb3';


-- Case D : master condition, which can be evaluated on table level inside the companyview 
plan select cpid, debname from companyview where cpname like '%Lim%';

-- Case E : Outside join evaluation
-- For the following sample, the master condition cv.cpid = inv.cpid or cv.cpid = 1
-- must be evaluated on level 0 of the query.
-- There is no chance to find any reduced or approprate cursor condition, which could be propagated to companyview
-- or invoice
plan select cpid, debname from companyview cv, invoice inv where cv.cpid = inv.cpid or cv.cpid = 1;


-- Case F : Select on view with two like condition. This still can be optimized via cursor conditions
-- splitted for each table, since we have a and condition
plan select cpid, debname from companyview cv where cv.cpname like '%Hugo%' and cv.debname like '%Deb%';

-- Case F : Select on view with two like conditions with lower function
-- This condtion can be nor more optimized with cursor condition, so master predicates are created for each table joine
plan select cpid, debname from companyview cv where lower(cv.cpname) like '%Hugo%' and  lower(cv.debname) like '%Deb%';


-- Case G : Or evaluation on plain table without index
-- 
plan select invid, invnr from invoice ibv where invstatus in ( 'EDIT', 'REVIEW' );

-- Case H : Order evaluation on view without index
-- 
plan select invid, invnr from invoiceview ibv where invstatus in ( 'EDIT', 'REVIEW' );

-- index creation on invstatus
create  btree invoice_b1 on invoice(invstatus);

-- Case I : Or evaluation on table with index
-- 
plan select invid, invnr from invoice ibv where invstatus in ( 'EDIT', 'REVIEW' );

-- Case J : Or evaluation on view with index
-- 
plan select invid, invnr from invoiceview ibv where invstatus in ( 'EDIT', 'REVIEW' );


-- Case K :  Prio or evaluation on view with index ( in tops like ) 
-- 
plan select invid, invnr from invoiceview ibv where invnr like 'RE-%' and invstatus in ( 'EDIT', 'REVIEW' );


-- Case K :  Prio compare evaluation on view  ( value compare tops in ) 
-- 
plan select invid, invnr from invoiceview ibv where invnr = 'RE-1' and invstatus in ( 'EDIT', 'REVIEW' );


-- Case L :  Multi in-expr condition, for both tables, index table scan should be used and both tables should be joined with master predicate cp.cpid = inv.cpid
-- 
plan select cp.cpid from invoice inv, company cp where inv.invstatus in ( 'EDIT', 'REVIEW' ) and cp.debnr in ( 10,20,30 ) and cp.cpid = inv.cpid;



-- Case M : check attribute mapping
--
drop if exists view invoicemapview;
create view invoicemapview as
select
    inv.invid as mapinvid,
    inv.invnr as mapinvnr,
    inv.invstatus as mapstatus
from invoiceview inv;

plan select mapinvid, mapstatus from invoicemapview where mapstatus in ( 'EDIT', 'REVIEW');


select distinct cpid from posrule where endbook is null or endbook > '01.02.2025';

-- Case N : check subselect filter
--

plan select i.cpid, c.cpname, min(i.invdate) from invoice i, company c where i.cpid = c.cpid and i.cpid in ( select cpid from posrule where endbook is null or endbook > '01.02.2025' ) group by i.cpid,c.cpname;



