/**************************************************************************************/
/* File:        demo05                                                                */
/* Project:     ATSQL2 : Workshop Demo                                                */
/* Author:      Rick Snodgrass                                                        */
/* Date:        08-17-1995                                                            */
/* Results:                                                                           */
/**************************************************************************************/

SET CLOCK TO TIMESTAMP '1995/01/01';

/************/
/* Level 1: */
/************/


/* Level 1 is identical to SQL: Upwards Compatibility */

CREATE TABLE employee(ename VARCHAR(12), eno INTEGER PRIMARY KEY,
                      street VARCHAR(22), city VARCHAR(10), birthday DATE);

INSERT INTO employee 
	VALUES ('Therese', 5873, 'Bahnhofstrasse 121', 'Zurich', DATE '1961/03/21');
INSERT INTO employee 
	VALUES ('Franziska', 6542, 'Rennweg 683', 'Zurich', DATE '1963/01/01');


CREATE TABLE salary(eno INTEGER REFERENCES employee(eno), amount INTEGER);

INSERT INTO salary VALUES (6542, 3200);
INSERT INTO salary VALUES (5873, 3300);


CREATE ASSERTION emp_has_sal CHECK
      (NOT EXISTS (
                  SELECT *
                  FROM employee AS e
                  WHERE NOT EXISTS (
                        SELECT *
                        FROM salary AS s
                        WHERE e.eno = s.eno)));



SELECT * FROM employee;

/*
     ename  eno             street   city     birthday
 --------- ---- ------------------ ------ ------------
   Therese 5873 Bahnhofstrasse 121 Zurich |1961/03/21|
 Franziska 6542        Rennweg 683 Zurich       |1963|
*/


SELECT * FROM salary;

/*
       eno    amount
 --------- ---------
      6542      3200
      5873      3300
*/


/* We update Therese's salary. Note that this update is not 'recorded', since salary 
   is a snapshot table! */

UPDATE salary s
SET    (amount) = (SELECT 1.1 * s.amount
                   FROM   salary s, employee e
                   WHERE  e.ename = 'Therese'
                   AND    s.eno = e.eno)
WHERE s.eno = (SELECT e.eno FROM employee e WHERE e.ename = 'Therese');


COMMIT;

SELECT * FROM salary;

/*
       eno    amount
 --------- ---------
      6542      3200
      5873      3630
*/


CREATE VIEW high_salary AS SELECT * FROM salary WHERE amount > 3500;

SELECT amount FROM high_salary;

/*
    amount
 ---------
      3630
*/


SELECT ename, city
FROM   salary AS s, employee AS e
WHERE  s.eno = e.eno AND amount > 3500;

/*
       ename      city
 ----------- ---------
     Therese    Zurich
*/



/************/
/* Level 2: */
/************/

SET CLOCK TO TIMESTAMP '1995/02/01';

/* We now retain the salary history: */

ALTER TABLE salary ADD VALID;

ALTER TABLE employee ADD VALID;



/* The following SET CLOCK shows the difference of
   the ALTER TABLE- and the INSERT-default valid time: */

SET CLOCK TO TIMESTAMP '1995/02/02';

INSERT INTO employee 
	VALUES('Lilian', 3463, '46 Speedway', 'Tucson', DATE '1970/03/09');
INSERT INTO salary VALUES(3463, 1010);

COMMIT;


VALID SELECT * FROM employee;

/*
                VALID     ename  eno             street   city     birthday
 -------------------- --------- ---- ------------------ ------ ------------
    [1995/02-forever)   Therese 5873 Bahnhofstrasse 121 Zurich |1961/03/21|
    [1995/02-forever) Franziska 6542        Rennweg 683 Zurich       |1963|
 [1995/02/02-forever)    Lilian 3463        46 Speedway Tucson |1970/03/09|
*/


VALID SELECT * FROM salary;

/*
                    VALID       eno    amount
 ------------------------ --------- ---------
        [1995/02-forever)      6542      3200
        [1995/02-forever)      5873      3630
     [1995/02/02-forever)      3463      1010
*/

 
/* Tables, views, queries act like before (TUC). */

SELECT ename, city
FROM   high_salary AS s, employee AS e
WHERE  s.eno = e.eno;

/*
       ename      city
 ----------- ---------
     Therese    Zurich
*/


/* Referential integrity acts like before: the following will abort due to 
   RI violation. */

INSERT INTO salary VALUES(4236, 4900);

VALID SELECT * FROM salary;

/*
                    VALID       eno    amount
 ------------------------ --------- ---------
        [1995/02-forever)      6542      3200
        [1995/02-forever)      5873      3630
     [1995/02/02-forever)      3463      1010
     [1995/02/02-forever)      4236      4900
*/

COMMIT;

/*
Error(s) found checking referential integrity * salary.eno references employee.eno *

Rollback
*/



/************/
/* Level 3: */
/************/

SET CLOCK TO TIMESTAMP '1995/03/01';

/* Modifications act like before, except that history is now retained. */

UPDATE employee
SET    street = '212 Aqua Caliente', city = 'Tucson'
WHERE  ename = 'Therese';


VALID SELECT * FROM employee;

/*
                VALID     ename  eno             street   city     birthday
 -------------------- --------- ---- ------------------ ------ ------------
    [1995/02-forever) Franziska 6542        Rennweg 683 Zurich       |1963|
 [1995/02/02-forever)    Lilian 3463        46 Speedway Tucson |1970/03/09|
    [1995/02-1995/03)   Therese 5873 Bahnhofstrasse 121 Zurich |1961/03/21|
    [1995/03-forever)   Therese 5873  212 Aqua Caliente Tucson |1961/03/21|
*/


UPDATE salary s
SET    (amount) = (SELECT 1.1 * s.amount
                   FROM   salary s, employee e
                   WHERE  e.ename = 'Therese'
                   AND    s.eno = e.eno)
WHERE s.eno = (SELECT e.eno FROM employee e WHERE e.ename = 'Therese');


VALID SELECT * FROM salary;

/*
                    VALID       eno    amount
 ------------------------ --------- ---------
        [1995/02-forever)      6542      3200
     [1995/02/02-forever)      3463      1010
        [1995/02-1995/03)      5873      3630
        [1995/03-forever)      5873      3993
*/

COMMIT;

/* Can retrieve the history (SR): */

VALID 
   SELECT ename, city
   FROM   salary AS s, employee AS e
   WHERE  s.eno = e.eno AND amount > 3500;


/*
                    VALID       ename      city
 ------------------------ ----------- ---------
        [1995/02-1995/03)     Therese    Zurich
        [1995/03-forever)     Therese    Tucson
*/


/* Can do complicated queries on each state. */
/* List those for which no one makes a higher salary in a different city. */

VALID 
   SELECT ename
   FROM   employee AS e1, salary AS s1
   WHERE  e1.eno = s1.eno
   AND NOT EXISTS (SELECT ename
                   FROM   employee AS e2, salary AS s2
                   WHERE  e2.eno = s2.eno
                   AND    s2.amount > s1.amount
                   AND    e1.city <> e2.city);

/*
                    VALID       ename
 ------------------------ -----------
        [1995/02-1995/03)     Therese
        [1995/03-forever)     Therese
        [1995/02-1995/03)   Franziska
*/


/* Each query with VALID returns a time-varying result. */


/* Contraints must hold over each state. The following will abort, due to
  a violation of the emp_has_sal constraint. */

DELETE FROM salary
WHERE  eno = 6542;

COMMIT;

/*
Error(s) found checking assertion * emp_has_sal *

Rollback
*/


/************/
/* Level 4: */
/************/

SET CLOCK TO TIMESTAMP '1995/04/01';

/* Can specify the period over which the modication applies. */

NONSEQUENCED VALID PERIOD '1996/01/01 - forever'
DELETE FROM salary
WHERE eno = 6542;


NONSEQUENCED VALID PERIOD '1996/01/01 - forever'
DELETE FROM employee
WHERE eno = 6542;

COMMIT;

VALID SELECT * FROM salary;

/*
                    VALID       eno    amount
 ------------------------ --------- ---------
     [1995/02/02-forever)      3463      1010
        [1995/02-1995/03)      5873      3630
        [1995/03-forever)      5873      3993
           [1995/02-1996)      6542      3200
*/

VALID SELECT * FROM employee;

/*
                VALID     ename  eno             street   city     birthday
 -------------------- --------- ---- ------------------ ------ ------------
 [1995/02/02-forever)    Lilian 3463        46 Speedway Tucson |1970/03/09|
    [1995/02-1995/03)   Therese 5873 Bahnhofstrasse 121 Zurich |1961/03/21|
    [1995/03-forever)   Therese 5873  212 Aqua Caliente Tucson |1961/03/21|
       [1995/02-1996) Franziska 6542        Rennweg 683 Zurich       |1963|
*/

/* RI and constraints must apply over each state. The following will abort
   because the emp_has_sal constraint is violated for certain states. */

NONSEQUENCED VALID PERIOD '1995/01/01-forever'
DELETE FROM salary
WHERE eno = 6542;

COMMIT;

/*
Error(s) found checking assertion * emp_has_sal *
.
Rollback
*/


/* Let's look at the history of salaries. */

VALID 
  SELECT ename, amount
  FROM   employee AS e, salary AS s
  WHERE  e.eno = s.eno;

/*
                    VALID       ename    amount
 ------------------------ ----------- ---------
     [1995/02/02-forever)      Lilian      1010
        [1995/02-1995/03)     Therese      3630
        [1995/03-forever)     Therese      3993
           [1995/02-1996)   Franziska      3200
*/



/************/
/* Level 5: */
/************/

SET CLOCK TO TIMESTAMP '1995/05/01';

/* Can execute non-sequenced queries. */
/* Who was given salary raises, and when? */


NONSEQUENCED VALID BEGIN(VALID(s2))
	(SELECT ename, s2.amount - s.amount diff
         FROM   employee AS e, salary AS s, salary AS s2
         WHERE  e.eno = s.eno AND e.eno = s2.eno
         AND    s2.amount > s.amount
         AND    VALID(s) MEETS VALID(s2)) (PERIOD);


/* 
             at       ename      diff
 -------------- ----------- ---------
      |1995/03|     Therese       363
*/

 

/********************/
/* Transaction time */
/********************/


/************/
/* Level 2: */
/************/

SET CLOCK TO TIMESTAMP '1995/06/01';

ALTER TABLE employee DROP VALID;

ALTER TABLE employee ADD TRANSACTION;

ALTER TABLE salary DROP VALID;


TRANSACTION SELECT * FROM employee;

/*
       TRANSACTION     ename  eno            street   city     birthday
 ----------------- --------- ---- ----------------- ------ ------------
 [1995/06-forever)    Lilian 3463       46 Speedway Tucson |1970/03/09|
 [1995/06-forever)   Therese 5873 212 Aqua Caliente Tucson |1961/03/21|
 [1995/06-forever) Franziska 6542       Rennweg 683 Zurich       |1963|
*/

COMMIT;

SET CLOCK TO TIMESTAMP '1995/07/01';


/* Modifications behave as before: */

UPDATE employee
SET    street = 'Niederdorfstrasse 2', city = 'Zurich'
WHERE  ename = 'Therese';

TRANSACTION SELECT * FROM employee;

/*
       TRANSACTION     ename  eno              street   city     birthday
 ----------------- --------- ---- ------------------- ------ ------------
 [1995/06-forever)    Lilian 3463         46 Speedway Tucson |1970/03/09|
 [1995/06-forever) Franziska 6542         Rennweg 683 Zurich       |1963|
 [1995/06-1995/07)   Therese 5873   212 Aqua Caliente Tucson |1961/03/21|
 [1995/07-forever)   Therese 5873 Niederdorfstrasse 2 Zurich |1961/03/21|
*/


COMMIT;

/* Queries act as before. */

SELECT ename, street, city
FROM   employee;

/*
       ename                street      city
 ----------- --------------------- ---------
      Lilian           46 Speedway    Tucson
   Franziska           Rennweg 683    Zurich
     Therese   Niederdorfstrasse 2    Zurich
*/



/************/
/* Level 3: */
/************/

SET CLOCK TO TIMESTAMP '1995/08/01';

/* Let's change a stored value. */

UPDATE employee
SET    street = 'Wilstr. 80'
WHERE  ename = 'Therese';

 
COMMIT;

/* We can get the history of the table. */
TRANSACTION 
        SELECT ename, street
        FROM   employee;

/*
       TRANSACTION     ename              street
 ----------------- --------- -------------------
 [1995/06-forever)    Lilian         46 Speedway
 [1995/06-forever) Franziska         Rennweg 683
 [1995/06-1995/07)   Therese   212 Aqua Caliente
 [1995/08-forever)   Therese          Wilstr. 80
 [1995/07-1995/08)   Therese Niederdorfstrasse 2
*/



/************/
/* Level 5: */
/************/


SET CLOCK TO TIMESTAMP '1995/09/01';

/* Queries can be asked about different states. */
/* When was the street changed? */

NONSEQUENCED TRANSACTION 
	SELECT e1.ename, e1.street as old, e2.street as new, 
	       BEGIN(TRANSACTION(e2)) AS trans
	FROM   employee AS e1, employee AS e2
	WHERE  e1.eno = e2.eno AND TRANSACTION(e1) MEETS TRANSACTION(e2);

/*
    e1.ename                   old                   new          trans
 ----------- --------------------- --------------------- --------------
     Therese     212 Aqua Caliente   Niederdorfstrasse 2      |1995/07|
     Therese   Niederdorfstrasse 2            Wilstr. 80      |1995/08|
*/



/**************/
/* Bitemporal */
/**************/

/************/
/* Level 2: */
/************/

SET CLOCK TO TIMESTAMP '1995/10/01';

ALTER TABLE salary ADD VALID;
ALTER TABLE salary ADD TRANSACTION;

ALTER TABLE employee ADD VALID;

COMMIT;


SET CLOCK TO TIMESTAMP '1995/11/01';

/* Modifications work the same: */

UPDATE salary
SET    (amount) = (SELECT amount - 200 FROM salary WHERE eno = 5873)
WHERE  eno = 5873;

COMMIT;

VALID AND TRANSACTION SELECT * FROM employee;

/*
       TRANSACTION             VALID     ename  eno              street   city     birthday
 ----------------- ----------------- --------- ---- ------------------- ------ ------------
 [1995/10-forever) [1995/10-forever)    Lilian 3463         46 Speedway Tucson |1970/03/09|
 [1995/10-forever) [1995/10-forever) Franziska 6542         Rennweg 683 Zurich       |1963|
 [1995/10-forever) [1995/10-forever)   Therese 5873          Wilstr. 80 Zurich |1961/03/21|
*/


VALID AND TRANSACTION SELECT * FROM salary;

/*
       TRANSACTION             VALID  eno amount
 ----------------- ----------------- ---- ------
 [1995/10-forever) [1995/10-forever) 3463   1010
 [1995/10-forever) [1995/10-forever) 6542   3200
 [1995/11-forever) [1995/10-1995/11) 5873   3993
 [1995/11-forever) [1995/11-forever) 5873   3793
 [1995/10-1995/11) [1995/10-forever) 5873   3993
*/


/* Queries and views work the same. */

SELECT ename, city
FROM   high_salary AS s, employee AS e
WHERE  s.eno = e.eno;

/*
       ename      city
 ----------- ---------
     Therese    Zurich
*/


/************/
/* Level 3: */
/************/

/* Queries can be asked about individual states. Here, we will get a
history in both valid and transaction time. */

VALID AND TRANSACTION 
	SELECT ename, city
	FROM   salary AS s, employee AS e
	WHERE  s.eno = e.eno AND amount > 3500;

/*
       TRANSACTION             VALID   ename   city
 ----------------- ----------------- ------- ------
 [1995/11-forever) [1995/10-1995/11) Therese Zurich
 [1995/11-forever) [1995/11-forever) Therese Zurich
 [1995/10-1995/11) [1995/10-forever) Therese Zurich
*/



/************/
/* Level 4: */
/************/

SET CLOCK TO TIMESTAMP '1995/12/01';

VALID AND TRANSACTION SELECT * FROM salary;

/*
       TRANSACTION             VALID  eno amount
 ----------------- ----------------- ---- ------
 [1995/10-forever) [1995/10-forever) 3463   1010
 [1995/10-forever) [1995/10-forever) 6542   3200
 [1995/11-forever) [1995/10-1995/11) 5873   3993
 [1995/11-forever) [1995/11-forever) 5873   3793
 [1995/10-1995/11) [1995/10-forever) 5873   3993
*/


/* Can specify the (valid-time) period of applicability also for
   bitemporal tables. This is both a retroactive and a postactive update. */

NONSEQUENCED VALID PERIOD '1995/08/01-forever'
UPDATE salary
SET    amount = 4000
WHERE  eno = 5873;

VALID AND TRANSACTION SELECT * FROM salary;

/*
              TRANSACTION                    VALID       eno    amount
 ------------------------ ------------------------ --------- ---------
        [1995/10-forever)        [1995/10-forever)      3463      1010
        [1995/10-forever)        [1995/10-forever)      6542      3200
        [1995/10-1995/11)        [1995/10-forever)      5873      3993
        [1995/11-1995/12)        [1995/10-1995/11)      5873      3993
        [1995/11-1995/12)        [1995/11-forever)      5873      3793
        [1995/12-forever)        [1995/10-1995/11)      5873      4000
        [1995/12-forever)        [1995/11-forever)      5873      4000
*/


/* Let's look at the history now. */
VALID AND TRANSACTION 
  SELECT ename, amount
  FROM   employee, salary
  WHERE  employee.eno = salary.eno;

/*
              TRANSACTION                    VALID       ename    amount
 ------------------------ ------------------------ ----------- ---------
        [1995/10-forever)        [1995/10-forever)      Lilian      1010
        [1995/10-forever)        [1995/10-forever)   Franziska      3200
        [1995/10-1995/11)        [1995/10-forever)     Therese      3993
        [1995/11-1995/12)        [1995/10-1995/11)     Therese      3993
        [1995/11-1995/12)        [1995/11-forever)     Therese      3793
        [1995/12-forever)        [1995/10-1995/11)     Therese      4000
        [1995/12-forever)        [1995/11-forever)     Therese      4000
*/


/************/
/* Level 5: */
/************/

SET CLOCK TO TIMESTAMP '1995/12/01';

/* Arbitrarily complex non-sequenced queries can be specified. This query
   is SR in valid time. */
/* When was a salary corrected? */

NONSEQUENCED TRANSACTION AND VALID 
	(SELECT s2.eno, BEGIN(TRANSACTION(s2)) AS ttime
	 FROM   salary as s1, salary as s2
	 WHERE  NOT s1.amount=s2.amount AND TRANSACTION(s1) MEETS TRANSACTION(s2)) (PERIOD);


/*
                    VALID    s2.eno          ttime
 ------------------------ --------- --------------
        [1995/11-forever)      5873      |1995/11|
        [1995/10-forever)      5873      |1995/12|
*/


DROP TABLE salary;
DROP TABLE employee;
DROP VIEW high_salary;
DROP ASSERTION emp_has_sal;

REMOVE CLOCK;
